Why #Resource can't work in HttpServlet? - spring

I am tiro to Spring, and want to use auto wire with annotation #Resource in my servlet.
In service layer and dao layer, this annotation works well, when I use it in my Servlet, the exception comes:
com.fruit.action.merchant.MerAdd.service name='merAddService' is an unknown #Resource
as you see, MerAdd is a servlet extends my own BaseServlet which extends HttpServlet, service is an object of MerAddServie, in MerAdd servlet:
#Resource(name="merAddService")
private MerAddBusiness service;
public MerAddBusiness getService() {
return service;
}
public void setService(MerAddBusiness service) {
this.service = service;
}
Is there anything I should do to fix this problem, mybe I misunderstand #Resource, can you help me , thanks ahead~

Unfortunately You cannot autowire using #Resource annotaion in Servlet.
Same Question is discussed in this spring forum link
Problem:-"The problem here is that some J2EE components have dependencies injected into them by the web container. Which means that #Resource() annotations won't work -- the container will try to resolve those dependencies to JNDI (or somewhere else)."
Possible Workaround:-
As you can use #Autowired annotation in your servlet
So You can delegate request processing to the dedicated bean which will have #Resource Bean autowired in it , i.e. make your servlet to be just an entry point that conforms to the API supported by servlet container. Hence, you can configure that actual business logic holder bean as necessary via spring and just retrieve it from IoC container and call necessary method from the servlet

Related

Spring boot jersey - prevent startup instantiation of controller

I am using spring boot with web and jersey (spring-boot-jersey-starter). I have a Jersey endpoint that needs to inject a request scope bean. However, at startup of the application I am getting a no bean found error.
#Component
#Path("blah")
#RequestScoped
public class JerseyController{
#Inject
private MyEntity entity;
}
#Component
public class JerseyConfiguration extends ResourceConfig{
public JeyseyConfiguration(){
register(JeyseyController.class);
registere(MyEntityProvider.class);
}
}
Is there a way, in a spring-boot web app, to prevent Spring from attempting to instantiate and inject my JerseyController until an HTTP request is received so that the injected dependency can be provided by my Jersey provider?
#Component is not required on Jersey resources. Having it will cause Spring to instantiate it (with default Singleton scope). I don't think Spring doesn't respect the #RequestScoped. This is a Jersey annotation. If you want to use the #Component, I think the Spring #Scope("request") might do the trick though.
You can also remove the #RequestScoped. This is the default scope for Jersey resources.
The only time I have ever found a need to use #Component on Jersey resources, is if I need to use the Spring #Value (maybe AOP also, but I don't do much AOP). Other than that, the Jersey-Spring integration already supports the most common used feature of Spring which is DI. And if you really want to make the Jersey resource a singleton, Jersey supports the #Singleton annotation.

#ControllerAdvice with #Autowired dependency not being injected

Anyone knows how to inject a dependency to a #ControllerAdvice?
My #ControllerAdvice extends Spring's ResponseEntityExceptionHandler and implements no interfaces.
The #ControllerAdvice gets called correctly, but the #Autowired dependency is never injected. There are no startup injection errors, the dependency is simply null.
I guess it has to do with how Spring proxies the #ControllerAdvice with cglib so that the #Autowired annotation gets lost.
I tested by implementing an interface, so that Spring could create a JDK proxy but it didn't work either. Actually with an interface, it didn't even gets called at all... even if I also annotate the interface with #ControllerAdvice.
Is there a way to specify that Spring should use JDK proxies for that particular case?
EDIT: I'm using Spring 3.2.4.RELEASE, by the way.
Sample class:
#ControllerAdvice
public class RestExceptionHandler extends ResponseEntityExceptionHandler {
#Autowired(required = true)
public AuditService auditService;
#ExceptionHandler(value = { RuntimeException.class })
public final ResponseEntity<Object> handleRuntimeException(Exception ex, WebRequest request) {
// auditService is null here!
}
}
In your case your bean is behind a CGLIB proxy.
It creates a subclass of your bean and as the method has final modifier it can't change the behavior of the original ResponseEntityExceptionHandler class to insert a call to the bean behind - please check my other answer about CGLIB.
CGLIB proxy is a different object that delegates the method calls to the original bean.
Please note that it would not be possible to implement much of Spring functionality only with subclassing i.e. without this separation of objects. How would it work when singleton-scoped bean references a session-scoped bean - obviously there are many session-scope beans and only one singleton-scoped bean.

Wiring beans into TestNG listener that implements IInvokedMethodListener

I have a TestNG listener that implements IInvokedMethodListener. I would like to wire in a Spring bean inside this listener and use it. Unfortunately, this class is instantiated by TestNG and so Spring cannot wire anything in that is annotated using #Autowired. I tried implementing ApplicationContextAware, but that doesn't work either.
Is there a way to wire Spring beans into classes that implement IInvokedMethodListener?
ApplicationContextAware only works for Spring Beans. You can use #Configurable, but that requires AspectJ.
Here's a simple hack that should work: Add a static member to your listener class and inject it via a non-static setter.
public class MyMethodListener implements IInvokedMethodListener {
private static MyBean myBean;
#Autowired
public void setMyBean(MyBean myBean) {
MyMethodListener.myBean = myBean;
}
}
Include a bean of the required type in your application context.
The listener instantiated by TestNG will not be the same instance as the one from the Spring context, but it will have the static member set, provided that context creation has finished before TestNG instantiates the listener.
I had the same problem recently, it is basically Listeners are not maintained by spring. So I did some googling around this concept like "Injecting beans into classes not managed by spring", I got https://dzone.com/articles/autowiring-spring-beans-into-classes-not-managed-by-spring link which explains exactly the same problem and the solution. It worked for me.

Prevent autowiring by type for certain beans in Spring

In my spring context I am creating a service bean and a proxy for this service bean (explicitly). Both implement the same interface.
Can I ensure that autowiring cannot inject the target bean?
I would like to be able to use the target service with the #Resource or #Qualifier annotations, but when autowiring it should always be the proxy.
Any ideas?
Use the Primary annotation. It will indicate which bean should be use preferably when autowiring.
Hope this helps :)
You can put #Primary annotation in your proxy service like bellow:
#Primary
#Repository
public class ProxyOfSomeService implements SomeService
And after that when you use, #Autowired annotation on SomeService field, the ProxyOfSomeService will be injected by deafault.
But when you need the real service you can have it like bellow:
#Autowired
#Resource(name="someRealService")
private SomeService someService;
I think this serves your need, thanks!

How to use Spring services in JSF-managed beans?

JSF is very popular technology in Java world, however, cooperation with Spring is still painfull and requires 'nasty' hacks. I have currently the problem with one of this 'hacks'.
Spring services are injected using the SpringBeanFacesELResolver. It is configured in faces-config.xml:
<application>
<el-resolver>
org.springframework.web.jsf.el.SpringBeanFacesELResolver
</el-resolver>
</application>
The injection of Spring services is very ugly, but it is working:
#ManagedProperty(value="#{customerService}")
CustomerService customerService;
But there are issues. JSF requires from me that the managed bean should be serializable. That means, that the Spring service must also be serializable, or the field should be transient. When the field is transient, the injection is not working (I have null in that field). And making Spring services serializable is in my opinion not a good idea and a potential performance issues - what should happen with Hibernate context, data sources, which all are injected into Spring service?
So, what is the correct and less painfull way of using Spring services withing JSF managed beans?
I experienced a lot of issues with org.springframework.web.jsf.el.SpringBeanFacesELResolver, too. Mostly related to unmatching object scopes (Spring has no equivalent to JSF's view scope and conversation scope). Some people also complain about serialization problems.
I successfully applied the solution proposed in this article: http://www.beyondjava.net/blog/integrate-jsf-2-spring-3-nicely/.
In my case, serialization, was not a problem and I was only concerned with bean scopes. I wished JSF to fully manage the backing beans lifecycle without interference with Spring beans lifecycle.
I made JSF managed beans to load the Spring context and autowire themselves to access Spring-managed beans from the JSF context.
I developed the following JSF bean superclass:
public abstract class AutowireableManagedBean {
protected AutowireCapableBeanFactory ctx;
#PostConstruct
protected void init() {
logger.debug("init");
ctx = WebApplicationContextUtils
.getWebApplicationContext(
(ServletContext) FacesContext.getCurrentInstance()
.getExternalContext().getContext())
.getAutowireCapableBeanFactory();
// The following line does the magic
ctx.autowireBean(this);
}
...
}
Then, my concrete JSF backing beans looked like this (I was able to use view scope without problems):
#ManagedBean
#ViewScoped
public class MyBackingBean extends AutowireableManagedBean {
#Autowired
private MyDao myDao;

Resources