how to get configKey in custom feign decode - spring-cloud-feign

I have several APIs defined in a TestFeignClient:
#FeignClient(name = "testFeign", url = "xxx")
public interface TestFeignClient {
#CustomAnnotation(value = 1)
#GetMapping("/test2")
String test1();
#CustomAnnotation(value = 2)
#GetMapping("/test2")
String test2();
}
also I define a custom decoder like this:
public class MyDecoder implements Decoder {
#Override
public Object decode(Response response, Type type) {
// how to get the #CustomAnnotation value in this method ?
return null;
}
}
my question is how can I get the #CustomAnnotation value in the decoder method ??

Related

How to change constructor arguments?

I have a record that performs a verification in its constructor as such :
public record Configuration(URI url) {
public Configuration(URI url) {
Validate.httpValid(url, "url");
}
}
Where the httpValid method is :
public static URI httpValid(final URI value, final String property) {
try {
value.toURL();
} catch (IllegalArgumentException | MalformedURLException e) {
throw new InvalidPropertyValueException(property, "httpValid", value, Map.of());
}
return value;
}
This however fails the test i'm trying to create :
#Test
void Should_RespectEqualsContract() {
EqualsVerifier
.forClass(Configuration.class)
.withPrefabValues(
Configuration.class,
new Configuration(URI.create("http://a.com")),
new Configuration(URI.create("http://b.com")))
.verify();
}
This is because EqualsVerifier is trying to create an object with "x" as argument :
InvalidPropertyValueException: The value x is not a valid httpValid as url
You're very close. You shouldn't provide the class that you're testing as a prefab value; instead you need to provide the paramter that's causing trouble, like this:
#Test
void Should_RespectEqualsContract() {
EqualsVerifier
.forClass(Configuration.class)
.withPrefabValues(
URI.class,
URI.create("http://a.com"),
URI.create("http://b.com"))
.verify();
}

can built_value deserialize generics like this?

all my JSON data contains status(int), msg(String), and data(any Type). Because I'm come from java ,I want use generics。I'm writing a deserialize for a top generics with built_value, but failed.
I have try this
https://github.com/google/built_value.dart/blob/master/end_to_end_test/test/generics_serializer_test.dart.
But do not really understand.
There follows my code:
abstract class GenericValue<T>
implements Built<GenericValue<T>, GenericValueBuilder<T>> {
T get data;
int get status;
String get msg;
GenericValue._();
static Serializer<GenericValue> get serializer => _$genericValueSerializer;
factory GenericValue([updates(GenericValueBuilder<T> b)]) =
_$GenericValue<T>;
}
abstract class UserInfo implements Built<UserInfo, UserInfoBuilder> {
static Serializer<UserInfo> get serializer => _$userInfoSerializer;
String get id;
String get email;
UserInfo._();
factory UserInfo([updates(UserInfoBuilder b)]) = _$UserInfo;
}
GenericValue<UserInfo> parseUserInfo(String jsonStr) {
final parsed = json.jsonDecode(jsonStr);
final specifiedType = const FullType(GenericValue, [FullType(UserInfo)]);
final serializersWithBuilder = (standardSerializers.toBuilder()
..addBuilderFac`enter code here`tory(specifiedType, () => GenericValueBuilder<UserInfo>
()))
.build();
Response<UserInfo> response = serializersWithBuilder.deserialize(parsed,
specifiedType: specifiedType);
return response;
}
but result is: Invalid argument(s): Unknown type on deserialization. Need either specifiedType or discriminator field.
how can it do it in right way, to deserialize JSON data like this.
String toJsonUserInfo() {
final specifiedType = const FullType(GenericValue, [FullType(UserInfo)]);
final serializersWithBuilder = (standardSerializers.toBuilder()
..addBuilderFactory(
specifiedType, () => GenericValueBuilder<UserInfo>()))
.build();
return json.encode(
serializersWithBuilder.serialize(this, specifiedType: specifiedType));
}
static GenericValue<UserInfo> fromJsonUserInfo(String jsonString) {
final specifiedType = const FullType(GenericValue, [FullType(UserInfo)]);
final serializersWithBuilder = (standardSerializers.toBuilder()
..addBuilderFactory(
specifiedType, () => GenericValueBuilder<UserInfo>()))
.build();
return serializersWithBuilder.deserialize(json.decode(jsonString),
specifiedType: specifiedType);
}
it works.

Skip a method execution to unit test controller flow [duplicate]

This question already has answers here:
How to Mock/Stub or simply ignore HttpRequest when unit testing [duplicate]
(2 answers)
Closed 7 years ago.
public class DemoController : Controller
{
private readonly ICommonOperationsRepository _commonRepo;
public DemoController (ICommonOperationsRepository commonRepo)
{
_commonRepo = commonRepo;
}
public ActionResult Default()
{
var model = new DemoModel();
try
{
**ConcreteClass cc = new ConcreteClass(Request.ServerVariables["HTTP_X_REWRITE_URL"].ToString());
cc.ConcreteClassMethod();**
model.ListTopListing.AddRange(_commonRepo.GetListings());
}
catch (Exception ex)
{
ExceptionHandler objErr = new ExceptionHandler(ex, "DemoController .Default()\n Exception : " + ex.Message);
objErr.LogException();
}
return View(model);
}
}
I am trying to unit test my controller. ConcreteClass constructor and its method ConcreteClassMethod both have some dependency on HttpRequest variables which i am not able to pass from my unit tests.
I want a way by which i can simply skip execution of ConcreteClass's constructor and ConcreteClassMethod when I am calling Default action of DemoController.
You can't create a new instance of an object and stop the constructor from being called. You would have to create an empty parameterless constructor.
public class ConcreteClass
{
private string MyString;
// Your constructor
public ConcreteClass(string myString)
{
this.MyString = myString;
}
// Parameterless constructor
public ConcreteClass()
{
// Do nothing, no code
}
// A method that might use MyString
public void DoSomethingWithMyString()
{
var trimmedString = this.MyString.Trim();
}
}
Either that or re-factor the way that your methods work so that it doesn't rely on having a string passed in on the constructor:
public class ConcreteClass
{
// No constructor required anymore
// Pass the string in to the methods that need the string
public void DoSomethingWithMyString(string myString)
{
var trimmedString = myString.Trim();
}
// Pass the string in to the methods that need the string
public void DoSomethingElseWithMyString(string myString)
{
var trimmedString = Int32.Parse(myString);
}
}
However, that probably doesn't solve the problem, bearing in mind that you want to inject your Request variable and you don't have access to them, can't you just do the following:
public class DemoController : Controller
{
private string HttpRewriteUrl;
public DemoController()
{
this.HttpRewriteUrl = Request.ServerVariables["HTTP_X_REWRITE_URL"].ToString();
}
// Custom constructor for unit testing
public DemoController(string httpRewriteUrl)
{
this.HttpRewriteUrl = httpRewriteUrl;
}
public ActionResult Default()
{
// Get the value from the object
ConcreteClass cc = new ConcreteClass(this.HttpRewriteUrl);
cc.ConcreteClassMethod();
}
}
Now within your Unit Tests you can use the second constructor and pass the value in:
var controller = new DemoController("your value to pass in here");
controller.Default();

Decoration using Castle DynamicProxy and StructureMap 3 in a Convention - DecorateAllWith

How to use DecorateAllWith to decorate with a DynamicProxy all instances implements an interface?
For example:
public class ApplicationServiceInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
// ...
invocation.Proceed();
// ...
}
}
public class ApplicationServiceConvention : IRegistrationConvention
{
public void Process(Type type, Registry registry)
{
if (type.CanBeCastTo<IApplicationService>() && type.IsInterface)
{
var proxyGenerator = new ProxyGenerator();
// ??? how to use proxyGenerator??
// ???
registry.For(type).DecorateAllWith(???); // How to use DecorateAllWith DynamicProxy ...??
}
}
}
I could decorate some interfaces to concrete types using (for example):
var proxyGenerator = new ProxyGenerator();
registry.For<IApplicationService>().Use<BaseAppService>().DecorateWith(service => proxyGenerator.CreateInterfaceProxyWithTargetInterface(....))
But havent able to using DecorateAll to do this.
To call registry.For<>().Use<>().DecorateWith() I have to do this:
if (type.CanBeCastTo<IApplicationService>() && !type.IsAbstract)
{
var interfaceToProxy = type.GetInterface("I" + type.Name);
if (interfaceToProxy == null)
return null;
var proxyGenerator = new ProxyGenerator();
// Build expression to use registration by reflection
var expression = BuildExpressionTreeToCreateProxy(proxyGenerator, type, interfaceType, new MyInterceptor());
// Register using reflection
var f = CallGenericMethod(registry, "For", interfaceToProxy);
var u = CallGenericMethod(f, "Use", type);
CallMethod(u, "DecorateWith", expression);
}
Only for crazy minds ...
I start to get very tired of StructureMap, many changes and no documentation, I have been read the source code but ... too many efforts for my objective ...
If someone can give me a bit of light I will be grateful.
Thanks in advance.
In addition ... I post here the real code of my helper to generate the expression tree an register the plugin family:
public static class RegistrationHelper
{
public static void RegisterWithInterceptors(this Registry registry, Type interfaceToProxy, Type concreteType,
IInterceptor[] interceptors, ILifecycle lifecycle = null)
{
var proxyGenerator = new ProxyGenerator();
// Generate expression tree to call DecoreWith of StructureMap SmartInstance type
// registry.For<interfaceToProxy>().Use<concreteType>()
// .DecoreWith(ex => (IApplicationService)
// proxyGenerator.CreateInterfaceProxyWithTargetInterface(interfaceToProxy, ex, interceptors)
var expressionParameter = Expression.Parameter(interfaceToProxy, "ex");
var proxyGeneratorConstant = Expression.Constant(proxyGenerator);
var interfaceConstant = Expression.Constant(interfaceToProxy);
var interceptorConstant = Expression.Constant(interceptors);
var methodCallExpression = Expression.Call(proxyGeneratorConstant,
typeof (ProxyGenerator).GetMethods().First(
met => met.Name == "CreateInterfaceProxyWithTargetInterface"
&& !met.IsGenericMethod && met.GetParameters().Count() == 3),
interfaceConstant,
expressionParameter,
interceptorConstant);
var convert = Expression.Convert(methodCallExpression, interfaceToProxy);
var func = typeof(Func<,>).MakeGenericType(interfaceToProxy, interfaceToProxy);
var expr = Expression.Lambda(func, convert, expressionParameter);
// Register using reflection
registry.CallGenericMethod("For", interfaceToProxy, new[] {(object) lifecycle /*Lifecicle*/})
.CallGenericMethod("Use", concreteType)
.CallNoGenericMethod("DecorateWith", expr);
}
}
public static class CallMethodExtensions
{
/// <summary>
/// Call a method with Generic parameter by reflection (obj.methodName[genericType](parameters)
/// </summary>
/// <returns></returns>
public static object CallGenericMethod(this object obj, string methodName, Type genericType, params object[] parameters)
{
var metod = obj.GetType().GetMethods().First(m => m.Name == methodName && m.IsGenericMethod);
var genericMethod = metod.MakeGenericMethod(genericType);
return genericMethod.Invoke(obj, parameters);
}
/// <summary>
/// Call a method without Generic parameter by reflection (obj.methodName(parameters)
/// </summary>
/// <returns></returns>
public static object CallNoGenericMethod(this object obj, string methodName, params object[] parameters)
{
var method = obj.GetType().GetMethods().First(m => m.Name == methodName && !m.IsGenericMethod);
return method.Invoke(obj, parameters);
}
}
Almost two years later I have needed return this issue for a new project. This time I have solved it this time I have used StructureMap 4.
You can use a custom interceptor policy to decorate an instance in function of his type. You have to implement one interceptor, one interceptor policy and configure it on a registry.
The Interceptor
public class MyExInterceptor : Castle.DynamicProxy.IInterceptor
{
public void Intercept(Castle.DynamicProxy.IInvocation invocation)
{
Console.WriteLine("-- Call to " + invocation.Method);
invocation.Proceed();
}
}
The interceptor policy
public class CustomInterception : IInterceptorPolicy
{
public string Description
{
get { return "good interception policy"; }
}
public IEnumerable<IInterceptor> DetermineInterceptors(Type pluginType, Instance instance)
{
if (pluginType == typeof(IAppService))
{
// DecoratorInterceptor is the simple case of wrapping one type with another
// concrete type that takes the first as a dependency
yield return new FuncInterceptor<IAppService>(i =>
(IAppService)
DynamicProxyHelper.CreateInterfaceProxyWithTargetInterface(typeof(IAppService), i));
}
}
}
Configuration
var container = new Container(_ =>
{
_.Policies.Interceptors(new CustomInterception());
_.For<IAppService>().Use<AppServiceImplementation>();
});
var service = container.GetInstance<IAppService>();
service.DoWork();
You can get a working example on this gist https://gist.github.com/tolemac/3e31b44b7fc7d0b49c6547018f332d68, in the gist you can find three types of decoration, the third is like this answer.
Using it you can configure the decorators of your services easily.

How do I sub in JSON.NET as model binder for ASP.NET MVC controllers?

It has been decided by the ASP.NET Web API team to use the JSON.NET library for model binding JSON data. However, "normal" MVC controllers still use the inferior JsonDataContractSerializer. This causes issues with parsing dates, and is causing me much headache.
See this for reference:
http://www.devcurry.com/2013/04/json-dates-are-different-in-aspnet-mvc.html
The author chooses to solve the issue in the Knockout layer on the client. But I would prefer to solve this by using the same JSON.NET model binder in MVC controllers as in Web API controllers.
How do I substitute a different JSON model binder into ASP.NET MVC? Specifically, the JSON.NET library. Using the same model binder from Web API would be ideal if possible.
I have done this, and also heavily customized the serialization that Json.NET is doing, by:
Replace the default formatter in global.asax.cs, Application_Start:
GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.JsonFormatter);
GlobalConfiguration.Configuration.Formatters.Add(new CustomJsonMediaTypeFormatter());
And my CustomJsonMediaTypeFormatter is:
public static class CustomJsonSettings
{
private static JsonSerializerSettings _settings;
public static JsonSerializerSettings Instance
{
get
{
if (_settings == null)
{
var settings = new JsonSerializerSettings();
// Must convert times coming from the client (always in UTC) to local - need both these parts:
settings.Converters.Add(new IsoDateTimeConverter { DateTimeStyles = System.Globalization.DateTimeStyles.AssumeUniversal }); // Critical part 1
settings.DateTimeZoneHandling = DateTimeZoneHandling.Local; // Critical part 2
// Skip circular references
settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
// Handle special cases in json (self-referencing loops, etc)
settings.ContractResolver = new CustomJsonResolver();
_settings = settings;
}
return _settings;
}
}
}
public class CustomJsonMediaTypeFormatter : MediaTypeFormatter
{
public JsonSerializerSettings _jsonSerializerSettings;
public CustomJsonMediaTypeFormatter()
{
_jsonSerializerSettings = CustomJsonSettings.Instance;
// Fill out the mediatype and encoding we support
SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));
SupportedEncodings.Add(new UTF8Encoding(false, true));
}
public override bool CanReadType(Type type)
{
return true;
}
public override bool CanWriteType(Type type)
{
return true;
}
public override Task<object> ReadFromStreamAsync(Type type, Stream stream, HttpContent content, IFormatterLogger formatterLogger)
{
// Create a serializer
JsonSerializer serializer = JsonSerializer.Create(_jsonSerializerSettings);
// Create task reading the content
return Task.Factory.StartNew(() =>
{
using (StreamReader streamReader = new StreamReader(stream, SupportedEncodings.First()))
{
using (JsonTextReader jsonTextReader = new JsonTextReader(streamReader))
{
return serializer.Deserialize(jsonTextReader, type);
}
}
});
}
public override Task WriteToStreamAsync(Type type, object value, Stream stream, HttpContent content, TransportContext transportContext)
{
// Create a serializer
JsonSerializer serializer = JsonSerializer.Create(_jsonSerializerSettings);
// Create task writing the serialized content
return Task.Factory.StartNew(() =>
{
using (StreamWriter streamWriter = new StreamWriter(stream, SupportedEncodings.First()))
{
using (JsonTextWriter jsonTextWriter = new JsonTextWriter(streamWriter))
{
serializer.Serialize(jsonTextWriter, value);
}
}
});
}
}
And finally, the CustomJsonResolver:
public class CustomJsonResolver : DefaultContractResolver
{
protected override IList<JsonProperty> CreateProperties(Type type, Newtonsoft.Json.MemberSerialization memberSerialization)
{
var list = base.CreateProperties(type, memberSerialization);
// Custom stuff for my app
if (type == typeof(Foo))
{
RemoveProperty(list, "Bar");
RemoveProperty(list, "Bar2");
}
return list;
}
private void RemoveProperty(IList<JsonProperty> list, string propertyName)
{
var rmc = list.FirstOrDefault(x => x.PropertyName == propertyName);
if (rmc != null)
{
list.Remove(rmc);
}
}
}
The JsonNetValueProviderFactory proposed here works better than the others I've tried (I had issues with arrays using Greg Ennis' one for example). This link also propose a solution to return Json from an action.

Resources