I wish to peel off a proxy object before serialization, and figured I could do that in JsonConverter.ReadJson().
However since the JsonConverter.ReadJson() is abstract, there is no default behavior to call after I strip off the proxy.
Is there such a thing as a DefaultJsonConverter I should derive from instead?
Related
Baeldung has this section:
this limits matching to join points where the bean reference is an
instance of the given type, while target limits matching to join
points where the target object is an instance of the given type. The
former works when Spring AOP creates a CGLIB-based proxy, and the
latter is used when a JDK-based proxy is created. Suppose that the
target class implements an interface:
public class FooDao implements BarDao {
...
}
In this case, Spring AOP will use the JDK-based proxy, and we should
use the target PCD because the proxied object will be an instance of
the Proxy class and implement the BarDao interface:
#Pointcut("target(com.baeldung.pointcutadvice.dao.BarDao)")
On the other hand, if FooDao doesn't implement any interface, or the
proxyTargetClass property is set to true, then the proxied object will
be a subclass of FooDao and we can use the this PCD:
#Pointcut("this(com.baeldung.pointcutadvice.dao.FooDao)")
I'm still confuse why this just works with CGLIB proxy and target just works with JDK proxy. Could you help to tell me the different between them?
Actually, the explanation in the tutorial does not make much sense:
Both this(MyInterface) and target(MyInterface) work for JDK proxies, if the bean is declared as a MyInterface type.
Both this(MyClass) and target(MyClass) work for CGLIB proxies, if the bean is declared as a MyClass type.
Just try, and you will see that I am right. In Spring AOP, there is not real difference between this() and target(), because due to its proxy-based nature, it implicitly only supports execution() pointcuts from AspectJ.
In native AspectJ however, you also have other pointcut types such as call(), and there you would see a difference: this() would match the caller's type, while target() would match the callee's type. E.g., if you intercept a method A.a() calling B.b() via pointcut call(B.b()), this() would return an A instance, while target() would return a B instance. Do not worry, if this is difficult to understand for you, because for Spring AOP and execution pointcuts it really does not matter.
The only subtle difference I noticed in Spring AOP is, that for MyInterfaceImpl implements MyInterface, pointcut target(MyInterfaceImpl) would actually match, while this(MyInterfaceImpl) would not. This is because for JDK proxies, the proxy actually extends java.lang.reflect.Proxy, not MyInterfaceImpl. The proxy only delegates to a MyInterfaceImpl instance.
Edit: If you keep in mind that, in contrast to native AspectJ which involves no dynamic proxies, the semantics in Spring AOP are such that
this() relates to the proxy object, while
target() relates to the proxied object (proxy target),
it becomes clear why in this special case for JDK proxies target() matches, but this() does not.
Reference: Spring manual, section "Declaring a pointcut - examples":
this(com.xyz.service.AccountService): Any join point (method execution only in Spring AOP) where the proxy implements the AccountService interface.
target(com.xyz.service.AccountService): Any join point (method execution only in Spring AOP) where the target object implements the AccountService interface.
Only in this case, we are not asking for the interface class (which both the proxy and the target object implement), but for the implementation class itself.
Bottom line: For all intents and purposes, in normal use cases you can use either this() or target() for both JDK and CGLIB proxies. I recommend to stick with target(), because it best matches the implicit execution() semantics of Spring AOP, and usually you are interested in information about the target rather than about the proxy..
Jackson's #JacksonInject annotation is useful for declaring properties of your deserialized object that are to be "injected" by the code calling for deserialization (as opposed to only being parsed from the JSON). To use this feature, it seems you have to either:
Set the InjectableValues into the ObjectMapper (which would tie them to that ObjectMapper instance and be used for all calls to it).
Get an ObjectReader [via ObjectMapper.reader(InjectableValues)] and use that ObjectReader directly to parse the JSON.
Unfortunately, neither of these is doable (from what I can see) when using Spring's RestTemplate without jumping through a lot of hoops. I don't want every object being deserialized from the RestTemplate to use injected values; nor do I see a way to customize how RestTemplate uses the underlying ObjectMapper1.
Is there a way to incorporate InjectableValues into RestTemplate's JSON deserialization?
1I suppose I could write my own custom HttpMessageConverter and figure out how to inject that into RestTemplate. But even then I don't see a way to pass the InjectableValues into ObjectMapper's read... methods. It's a lot of work even if I could.
I am putting together a very simple ByteBuddy delegate/proxy class.
The intention is (again, very simple) to proxy a class such that any of its non-final, non-private, non-static methods and so forth get routed to equivalent methods on its proxiedInstance field as returned by its getProxiedInstance method. (There should be exceptions made for the usual suspects: equals, hashCode, wait and notify and so on.)
I've set up my proxy class using the subclass strategy. I've also defined two methods, getProxiedInstance and setProxiedInstance, along with a private field named proxiedInstance of the proper type. I've done this using the FieldAccessor.ofBeanProperty() strategy. I've omitted that here for brevity and clarity. The class does in fact contain this field and these two methods.
Then I've defined the method interception like this, statically importing the relevant ElementMatchers methods:
builder
.method(not(isFinal()).and(not(isStatic())).and(not(isPrivate()))
.and((isPublic().and(named("toString")).and(takesArguments(0)).and(returns(String.class)))
.or((not(isDeclaredBy(Object.class)).and(not(named("getProxiedInstance"))).and(not(named("setProxiedInstance"))))))
)
.intercept(MethodDelegation.toMethodReturnOf("getProxiedInstance"));
In English: not final, not static, not private, and either the public String toString() method inherited from Object (or overridden), or any other method not declared by Object.class and not named getProxiedInstance or setProxiedInstance.
Suppose I have a class like this:
public class Frob {
public String sayHello() {
return "Hello!";
}
}
When I create a proxy class for it, instantiate it, and then call toString() on the proxy, I get Hello!.
This suggests to me somehow that the recipe I've quoted above is somehow routing toString() to sayHello().
From reading the MethodDelegation javadocs, it seems that maybe sayHello on the target/delegate object is picked for delegation because it is more specific than the method invoked on the proxy (toString). I guess name matching is lower priority than that.
I think this use case I have is relatively simple. How do I best accomplish it?
The best I could do, which works, but seems perhaps a little clunky or verbose, was this:
builder = builder
.method(not(isDeclaredBy(Object.class))
.and(not(isFinal()))
.and(not(isStatic()))
.and(not(isPrivate()))
.and(not(named("getProxiedInstance")))
.and(not(named("setProxiedInstance"))))
.intercept(MethodDelegation.toMethodReturnOf("getProxiedInstance"))
.method(is(toStringMethod))
.intercept(invoke(toStringMethod).onMethodCall(invoke(named("getProxiedInstance"))));
(toStringMethod is the Method resulting from Object.class.getMethod("toString").)
I think using MethodCall is a better approach to this. MethodDelegation is meant for "catch all proxies" where you inject corresponding dispatchers into what is often a single delegate method, maybe two. Method call is also much more performance since it does not need to do the analysis but just reroutes to a method of a compatible type.
I have a class A, a cache A_CACHE and a proxy object AProxy extends A. My goal is to serialize AProxy objects as if they are A objects (automatically substitute type) and put them into A_CACHE.
Is there any way in Apache Ignite to substitute type of an object that I am trying to put into cache (serialize using BinarySerializer)?
What I have tried so far.
I have implemented and registered the same BinarySerializer for both types. I have also tried to play with BinaryNameMapper class to return the same class name for both classes, but without success. The only option that comes to my mind now is to use BinaryObjectBuilder. Is it really the only option for me?
After a small research the solution was found.
AProxy should implement writeReplace method of Serializable interface. Return proxied instance from this method. If proxied class is Serializable or Externalizable and one wants to apply custom serialization, than Binarylizable interface should be implemented by proxied class (custom binary serializers are not applied when using the hack above, but instead OptimizedMarshaller is being used).
How can I globally configure json serializer for http4k? For example, snake case field names or formatting DateTime as ISO8601.
Since the ObjectMapper instance is private within ConfigurableJackson you cannot get at it after construction to do any configuration.
So you either need to construct your own direct instance of ConfigurableJackson and pass in a customized ObjectMapper or you need to subclass ConfigurableJackson with your own class. And then during the constructor, create an ObjectMapper (see example below) or intercept one being passed into your constructor and change its settings.
Whatever you do, be sure you do not break the http4k framework or anything else that might be using the same instance. You can see the defaults used by http4k declared in their source code:
object Jackson : ConfigurableJackson(ObjectMapper()
.registerModule(defaultKotlinModuleWithHttp4kSerialisers)
.disableDefaultTyping()
.configure(FAIL_ON_UNKNOWN_PROPERTIES, false)
.configure(FAIL_ON_IGNORED_PROPERTIES, false)
.configure(USE_BIG_DECIMAL_FOR_FLOATS, true)
.configure(USE_BIG_INTEGER_FOR_INTS, true)
)
You can use code similar to above to create your own instance.
See this thread for some conversation about this topic: https://github.com/http4k/http4k/issues/183
You don't necessarily need to extend ConfigurableJackson - it's just that extending it is the most convenient way to do this (in our experience).
All configuration is done by tweaking the ObjectMapper instance which is injected into the ConfigurableJackson constructor - the ConfigurableJackson itself just provides the wrapper API around that mapper. The question is to do with standard configuration of Jackson, so you should seek answers to your specific questions (snake case etc) from the Jackson docs directly as http4k doesn't own that API.