INTERFACES or TARGET_CLASS: Which proxyMode should I choose? - spring

I am looking for a way to store my object and it seems that the best approach is to use proxies. I found 2 annotation in the internet, which one should I use :
#Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)
or
#Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS )
Moreover, is it true that the proxies is the best way to use than using #Component
#Scope("session") or using #SessionAttributes?

You'll need to understand what each of those annotations does to choose for yourself. See the javadoc, here. Continue for a more detailed explanation.
The first
#Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)
creates
a JDK dynamic proxy implementing all interfaces exposed by the class of the target object
In other words, the proxy will be a subtype of the interfaces that the target object's class implements, but won't be a subclass of the target object's class itself.
Essentially Spring does the following
public class Example {
public static void main(String[] args) throws Exception {
Foo target = new Foo();
InvocationHandler proxyHandler = ... // some proxy specific logic, likely referencing the `target`
// works fine
Printable proxy = (Printable) Proxy.newProxyInstance(Example.class.getClassLoader(),
target.getClass().getInterfaces(), proxyHandler);
// not possible, ClassCastException
Foo foo = (Foo) proxy;
}
public static class Foo implements Printable {
#Override
public void print() {
}
}
public interface Printable {
void print();
}
}
The proxy returned won't be of type Foo and you therefore can't inject it into any targets of that type. For example, Spring will fail to inject it into a field like
#Autowired
private Foo foo;
but will successfully inject the proxy into a field like
#Autowired
private Printable printable;
All calls to the proxy will be handled by the InvocationHandler (which usually performs some use case specific logic then delegates to the target object).
The second annotation
#Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS )
creates
a class-based proxy (uses CGLIB).
In addition to interfaces, with CGLIB Spring will be able to create a proxy whose class is a subclass of the target's class. In essence, it does the following
Foo target = new Foo();
net.sf.cglib.proxy.Enhancer enhancer = new net.sf.cglib.proxy.Enhancer();
enhancer.setInterfaces(target.getClass().getInterfaces());
enhancer.setSuperclass(target.getClass());
net.sf.cglib.proxy.MethodInterceptor interceptor = ... // some proxy specific logic, likely referencing the `target`
enhancer.setCallback(interceptor);
// works fine
Foo proxy = (Foo) enhancer.create();
CGLIB creates a new class that is a subclass of Foo and instantiates it (invoking the constructor of Foo). All calls to the proxy will be intercepted by the provided callback (which usually performs some use case specific logic and then delegates to the target object).
Since the proxy class extends Foo, Spring can inject the proxy into a field (or constructor/method parameter) like
#Autowired
private Foo injectMe;
All this to say, if you're programming to interfaces, then ScopedProxyMode.INTERFACES will be sufficient. If you're not, then use ScopedProxyMode.TARGET_CLASS.
As for using #SessionAttributes, it is not an alternative to session scoped beans. Session attributes are just objects, they are not beans. They don't possess the full lifecycle, injection capabilities, proxying behavior that a bean may have.

If you want to store the whole bean in the session, use #Scope, otherwise use #SessionAttributes. In the case of using #Scope, if the class implements some interfaces then use INTERFACES proxy mode, if not use TARGET_CLASS.
Usually your service implements an interface, which allows the use of JDK proxies (INTERFACES mode). But if that is not the case then use TARGET_CLASS, which creates a CGLIB proxy.
Using INTERFACES should be used if possible and TARGET as last resort if the bean does not implement interfaces.

While going through a blog post provided in the comments above, I found a comment stating cons of interface-based proxies.
On the post, user Flemming Jønsson posted this:
Be careful with using interface-based proxies.
If you are using Spring Security or Spring Transactions you might experience oddities when using interface-based proxies.
E.g. if you have a bean T and that bean has methods a() and b() that are both annotated transactional. Calls from other beans directly to a() or b() will behave properly (as configured). However if you introduce an internal call - where a() calls b() then b's transactional metadata will have no effect. The reason is that when you are using interface-based proxies the internal call will not go through the proxy - and thus the transactional interceptor will not have a chance to start a new transaction.
The same goes for Security. If method a() only requires USER-role but calls b() that requires ADMIN-role, then the internal call from a to b will be performed for any USER with no warnings. Same reason as above, internal calls do not go through the proxy and thus the security interceptor does not have a chance to act upon the call to b() from a().
To solve issues like these use targetClass.

Related

Spring inject component into non-spring managed interface/abstract class and its subclasses

TLDR: I need an interface/abstract class and all classes implementing it to have access to a Spring managed bean. Can Spring inject a bean into an interface/abstract-class and its subclasses simply via #Autowired ?
I am working on an API built with Spring Webflux + Cloud Gateway that depending on the cookie JWT authorized party, identifies the User's policy group and assign an Attribute ENUM "InterfaceID" to the ServerWebExchange via exchange.getAttribute().put("InterfaceID",InterfaceID.A) after the JWT is validated, and currently uses "InterfaceID" to represent the different groups of users/different interface the user entered from.
JWTValidationFilter.java [Current]
switch(JWTValidator.validate(jwt).get("AZP")){
//if user is from company A or its partners
case "a":
case "aa":
exchange.getAttribute().put(InterfaceID.COMPANY_A_ACCESS);
break;
case "b":
exchange.getAttribute().put(InterfaceID.NORMAL_ACCESS);
...
}
For certain API endpoints (say /api/getSessionDocument), different "InterfaceID" fetches data from different DB/apis, as well as have different permission checking on top of that.
RequestController.java [Current]
#Autowired
APICallerUtil apiCallerUtil;
switch(exchange.getAttribute.get(InterfaceID)){
case "NORMAL_ACCESS":
apiCallerUtil.getDataFromApiA();
break;
case "COMPANY_A_ACCESS":
// call api B but check for permission from api D first
...
}
The endpoint's controller now has another switch statement, and to many code analyzers this have been a code smell. I have been trying to refactor this entire bit of code to use polymorphism to handle the different "getSessionDocument" flows, but i run into issues regarding the injection of util classes that calls specific APIs.
APICallerUtil.java class, exisiting class from the project, would prefer not to refactor this.
#Component
public class APICallerUtil{
#Value("${some uri to some API}") //different by environment and therefore cant be static final
private String uri1;
#Value("${some auth to some API}") //confidential
private String uri1AuthHeader;
//...
public JSONObject getDataFromApiA(String somekey){ //cant be static since uri1 is not static
//Some code that uses uri1 and apache httpclient
return data;
}
...
}
IBaseAccess.java
interface IBaseAccess{
default Mono<JSONObject> getSesssionDocument(ServerWebExchange e){return Mono.error("not implemented");}
}
RequestController.java [new]
#Autowired
APICallerUtil apiCallerUtil;
return exchange.getAttribute.get(InterfaceID).getSessionDocument(exchange);
NormalAccess.java
public class NormalAccess implements IBaseAccess{
//can i autowire APICallerUtil here?
//use constructor to pass the Util class reference here?
Mono<JSONObject> getSesssionDocument(ServerWebExchange e){
//need to call ApiA here
//need to call ApiC here
}
}
NormalAccess needs to call APICaller.getDataFromApiA(), but it needs a reference to the Spring managed instance of APICaller. What would be the "correct" way to pass the reference/autowire API caller into NormalAccess, or even better IBaseAccess (so that the implementing classes can use the Util bean)?
JWTValidationFilter.java [new]
switch(JWTValidator.validate(jwt).get("AZP")){
//if user is from company A or its partners
case "a":
case "aa":
exchange.getAttribute().put("InterfaceID",new CompanyAAccess(/*pass the util class here?*/));
break;
case "b":
exchange.getAttribute().put("InterfaceID",new NormalAccess(/*pass the util class here?*/));
...
}
I have tried several methods, but either I lack the knowledge on the specific Spring feature, or that method is deeemed a bad design choice by some, including:
Making the methods and fields in APICallerUtil static, via suggestions from Spring: How to inject a value to static field? and Assigning private static final field member using spring injection , then the Access classes can call the static methods.
Creating a contructor for IBaseAccess that consumes the APICallerUtil reference and store it inside. The JWTfilter would hold an autowired APICallerUtil and pass it in when the attribute is assigned.
Create a static class that provides the application context and Access classes use applicationContext.getBean("APICallerUtil"); to obtain the bean.
Use the #Configurable annotation? I could not find much documentation on how this works for interfaces/abstract-class.
I understand that there might not exist an absolute answer for this question, but regardless I'd like suggestion/feedback on which of these approaches are viable/good. Especailly concerning whether the APIUtil class should be static or not.

Null Pointer Exception In Spring Proxy Class and Kotlin

I am facing some problems with kotlin in conjunction with spring.
I have a controller bean (without an interface btw) which has an auto-wired service bean via the primary constructor.
It works perfectly unless I use caching annotations for the controller. Apparently springs caching generates a proxy class under the hood which deals with the caching.
My code looks like this:
#RestController
#RequestMapping("/regions/")
open class RegionController #Autowired constructor(val service: RegionService) {
#RequestMapping("{id}", method = arrayOf(RequestMethod.GET))
#Cacheable(cacheNames = arrayOf("regions"))
fun get(#PathVariable id: Long): RegionResource {
return this.service.get(id)
}
}
The problem now is a null pointer exception when the method is executed, actually this.service is null which technically is not possible as it is a nonnull variable in kotlin.
I assume that class proxies generated by spring initialize the class with null values instead of the autowired bean. This must be a common pitfall using kotlin and spring. How did you circumvent this problem?
In Kotlin both classes and members are final by default.
For the proxying library (CGLIB, javaassist) to be able to proxy a method it has to be declared non final and in a non final class (since those libraries implement proxying by subclassing). Change your controller method to:
#RequestMapping("{id}", method = arrayOf(RequestMethod.GET))
#Cacheable(cacheNames = arrayOf("regions"))
open fun get(#PathVariable id: Long): RegionResource {
return this.service.get(id)
}
You probably see a warning in console regarding RegionController methods not being subject to proxying.
The Kotlin compiler plugin
The Kotlin team has acknowledged this difficulty and created a plugin that marks the standard AOP proxy candidates e.g. #Component with open.
You can enable the plugin by in your build.gradle:
plugins {
id "org.jetbrains.kotlin.plugin.spring" version "1.1.60"
}
Soon this might not be a problem any longer.
There is work in progress that any lib (including spring for example) can specify a list of annotations a file in META-INF. Once a class is annotated with one of these, it will default to open for the class itself and all its functions. This is also true for classes inheriting from an annotated class.
For more details, have a look at https://github.com/Kotlin/KEEP/pull/40#issuecomment-250773204

Grails or Spring Method Level Transaction

I am new with spring/grails transaction and i am still not clear after reading so i am posting it in here,
I have a service class which is annotated as #Transactional
and i have methods some of them are annotated as
#Transactional(propagation = Propagation.REQUIRES_NEW)
and some of them are not.
#Transactional
class SomeService {
def findJob() {
MyInstance myInstance = getMeAJob();
if (myInstance) {
doSomeThing(myInstance)
doTask()
}
}
#Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception)
private doSomeThing(MyInstance myInst) {
myObj = MyInstance.lock(myInst.id)
try {
differentObj = doTask(myObj)
myObj.save()
doAnotherThing()
}
} catch (Exception e) {
log("Error in doAnotherTask")
}
}
private doAnotherThing(MyInstace myInst) {
perform some update on myInst
myInstant.save(flush: true)
}
private doTask() {
}
Suppose , I have transaction t1 from the class level and t2
transaction from doSomething()- REQUIRES_NEW.
Method that will execute in t1 - findJob() and doTask()
Method that will execute in t2 - doSomeThing() - doesn't affect the
"t1" in case of exception (Rollback)
Which one will be for doAnotherThing() method? Since I am calling it from doSomething()?
When you have a class-scope annotation, any method that's not annotated uses those settings, and annotated methods override the class-level settings with the settings from that annotation.
Note however that when using Spring's annotation support (with the #org.springframework.transaction.annotation.Transactional) annotation only public methods are supported. There won't be an error, but the annotations are silently ignored.
But even if you make doSomeThing public (either implicitly by removing the private keyword or explicitly by changing it to public) it won't do what you expect when you call doSomeThing from findJob. This is because Spring's annotation triggers the creation of a proxy of your class at runtime. The Spring bean that's registered for your service in that case is a proxy instance that has a "real" instance of your class as its delegate. All transactional public methods are intercepted by the proxy, which starts/joins/etc. a transaction and then calls your service method. Once you're "underneath" the proxy in the service instance all method calls are direct and any annotation settings have no effect. To get it to work you would need to call the method on the Spring bean and go through the proxy to start a new transaction.
To avoid this proxy issue, use the Grails #grails.transaction.Transactional annotation instead. It supports the same transaction features as the Spring annotation, but instead of creating a proxy, an AST transformation rewrites your methods to wrap them within a transaction. This makes it possible to make direct method calls like you're doing and create a new transaction or run under other transaction semantics as defined by the annotation attributes.
I did a talk a while back on using transactions in Grails that might shed some light.

Mocking a constructor of #Autowired service(system under test)

I have to mock jerseyclient which is being created in Constructor of subjected service. Subjected service is System under test injected via Spring's #Autowired.
In constructor of the service client=client.create() method is written. We can't change this code(Although this is a code smell). I want to mock the jersey client but it is in constructor of the service. I am not able to mock this
sooo... long story short.. admitting you use mockito, in your src for test you should have an applicationcontext for your test.. usually we define one programmatically so, something along those lines..
import the .xml file you use for test purpose (in my case i imported the one for the mailserver, for the connection and for the authentication) instead of the one i use for the "local" environmnet. After then define a method to setup each and every of your service.
You might need to add a mock for your template resolver as well, but ultimately this all depends on your stack...
So based on your approach the final thing might be a bit different, but ultimately you're gonna do something along the lines of what i outline below:
#Configuration
#ImportResource(value = {
"classpath:applicationContext-jdbc-test.xml",
"classpath:applicationContext-ldap-test.xml",
"classpath:applicationContext-mail-test.xml"})
public class ApplicationTestContext {
#Bean
public ObjectMapperWrapper objectMapperWrapper() {
return Mockito.mock(ObjectMapperWrapper.class);
}
#Bean
public YourService yourService() {
return new YourServiceImpl();
}
}

Why does Spring allow controller annotated request mappings on private methods?

Just came accross this today in a Spring MVC cotnroller class,
#RequestMapping(value = { "/foo/*" }, method = { RequestMethod.GET})
private String doThing(final WebRequest request) {
...
return "jsp";
}
This is making it a bit harder to write a test, I'll probably change it to public but what's the point of allowing mappings on private methods?
Java does not provide a mechanism for limiting the target of annotations based on access modifier.
As #smp7d stated, Java does not limit the target of annotations based on access modifiers, but syntactically speaking, #RequestMapping should not work on private methods. Also we cannot limit this, since it would break the backward compatibility. So, you can either go for defining your methods as public or you can create your own custom implementation.
Take a look at this: Spring's #RequestMapping annotation works on private methods

Resources