I'm working on a Spring MVC project and trying to integrate Apache Shiro for the security. Everything was going just swimmingly until I realized Hibernate was prematurely closing the session/connection after a single query and causing a lazyinit exception. Not surprising, what I was doing should be done within a transaction so the session isn't closed.
Dilemmas…
I tried putting #Transactional on my controller method, but I get 404's then. Looking at my logs, I can see that when Spring is bootstrapping it ignores any mappings in my HomeController if that #Transactional annotation is on any method within the controller.
Without the #Transactional and it loads up just fine, and Ih can see the RequestMappingHandlerMapping bean sees all the #RequestMapping annotations in my controller.
With #Transactional but without DefaultAdvisorAutoProxyCreator, and it works except Shiro annotations are simply ignored.
tldr: Shiro requires DefaultAdvisorAutoProxyCreator, but if I create that bean, Spring blows up when using the #Transactional annotation.
I'm asking for help because I'm completely at a loss for how to proceed at this point.
This is typically because when you put #Transactional on a method, Spring creates a dynamic proxy for that bean - if the bean implements an interface then dynamic proxy is created based on that interface, otherwise CGLIB will be used for creating the proxy.
The problem in your case, I am guessing is because you probably have based your controller on some interface, or you are extending it based on a base class. This is ending up creating a proxy based on that interface, because of this when it comes time for mappings to be created for your request, Spring MVC is probably not finding your mappings from your bean.
The fix could be a few:
a. You can try and force proxies to be based on CGLIB for your transactions:
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
b. You can use pure Aspectj,either load time weaving or compile time weaving
c. You can move the #Transactional into a Service (which has an interface) and delegate the call from the controller to the service, this way avoiding #Transaction on the controller
Related
This is somewhat weird behavior. I moved from Spring MVC to Spring Boot Configuration. This has caused the #Transactional method to throw the above error. Not sure why would switching from MVC to boot mvc do that. Anyone having nay idea about this?
I don't have specific code snippet as this is application wide and was working fine till I had Spring MVC. Now I moved to Spring Boot (Dependency upg. Filters moved etc.)
Flow for the methods having #Transactional is:
Action is called
If contains execute() which calls a Save method with #Transactional from a class which is implementation of an interface.
This class have another Dao method having #Transactional.
Thanks
I am upgrading my application from Spring3 to Spring 4. In my existing application we were using OpenSessionInViewInterceptor which creates the transaction along with new request.
Now I am using JPA also so even if I use OpenEntityManagerInViewInterceptor it doesn't associate transactions with it. So I had to put transaction manually in all my controller methods.
Due to legacy code, the controller classes have lots of business logic instead of distributing it properly to service layer.
Now if I put #Transctional annotation on controller method, then it doesn't work whereas if I use manual transaction through DefaultTransactionDefinition then it works properly.
Also, if I remove the business logic of controller methods to service layer, and put #Transactional annotation to service layer, then it also work fine. But these changes are tedious and my application is very big, so cant do it.
Please let me know why #Transactional doesn't work in my case if I put it in controller, how should I get it working.
I am not using AspectJ for transaction management.
Tried approaches:
Code at both places : code in dispatcher-servlet.xml along with appliacationContext.xml but still the controller transactions are failing.
Moved bean for urlMapping into applicationContext.xml but still it fails.
This question is regarding the sample:
https://github.com/spring-projects/spring-boot/blob/master/spring-boot-samples/spring-boot-sample-jersey/src/main/java/sample/jersey/Endpoint.java
Why do we need "#Component" annotation for Jersey resource when using spring-boot -starter-jersey project?
If I remove it, the Jersey servlet can still serve resources.
So what is the need for "#Component"?
You don't need it. Jersey uses HK2 as it's internal DI framework, and HK2 has a Spring bridge. This is what's used internally to bridge Spring components into the HK2 IoC container, so that they can be injected into Jersey components. And Jersey implements an AutowiredInjectionResolver1 that allows for injection of Spring components using #Autowired. You don't even need #Autowired though. All the Spring components can be injected with the normal #Inject.
The only drawback I've ran into, not making the Jersey components a Spring #Component is that it doesn't support #Value when you want to inject property values.
The one thing I don't like is that when you declare something a Spring #Component, it automatically makes it a singleton. But Jersey resources are by default request scoped. You can add a Spring #Scope("request"), and it should change the resource to a request scoped resource. Jersey has declared the Spring RequestScope, so we can use it. How exactly it ties in to Jersey's request scope, I am not a hundred percent sure. I ran into a problem a while back. I can't remember what it was, but that has kept me from ever using the Spring request scope again.
Assuming I want to keep all my resources request scoped, I would take sticking to the normal Jersey request scope, and not being able to inject #Values, over having to use Spring's request scope. Maybe I'm imagining things, and there was no issue using it, but personally I'll just stick to what I know works :-)
UPDATE
Another thing that does't work if you don't make the resource a Spring #Component is Spring's AOP. That's fine with me though as HK2 also has AOP.
1 - An InjectionResolver allows you to use custom annotations to create injection targets.
When you remove #Component jersey takes control of the scope of the instance. With #Component a singleton instance is created, removing it you can use the following jersey annotations:
• Request scope (Default):
By using the #RequestScope annotation or none, we can have a life-cycle till
the request lasts. This is the default scope of the root-resource classes. For
each new request, a new root-resource instance is being created and served
accordingly for the first time. However, when the same root-resource method
is being called, then the old instance will be used to serve the request.
• Per-lookup scope:
The #PerLookup annotation creates root-resource instances for every request.
• Singleton:
The #Singleton annotation allows us to create only a single instance
throughout the application.
Try different behaviors using a counter inside your class...
public class MyWebResource {
private int counter;
#GET
#Path("/counter")
#Produces(MediaType.APPLICATION_JSON)
public Response getCounter() {
counter++;
return Response.status(Status.OK).entity(counter).build();
}
}
I have a Spring/Struts2 problem and I have asked in Spring forum but no response
#Resource no injected sometimes
for the ease of reading I will repeat the question here. hopefully its not considered spamming
I have a very strange issue when I use #Resource to inject beans.
I am using Struts2 2.2.3.1 with provided Spring plugin with Spring 3.0.0. (I am not able to upgrade to the newest version of Spring without knowing the proper cause because all programs are in production)
The issue or observed problem is when an Struts2 Action is created, the fields annotated with #Resource are supposed to have resources injected by Spring. However, some times and only sometimes one of the annotated resources is not inject or the value is simply null and therefore causes NullPointerException. The point where problem occurs is undetermined which mean the same set of programs running in different environment will result in different behaviors. Also the resource that is not injected is not always the same.
For example, if there are actions A, B, C, and environment E1 and E2, in E1 the A action might have this problem sometimes and in E2 it might be action B that's having the problem. One thing that's certain is that if in E2 B is having problem it will happen from time to time and A and C wont have problem or at least the problem just not observed on A and C. Moreover, if A has 5 #Resource fields, when the problem occurs the NPE may be thrown when accessing the first resource however the next time may be the second resource.
Here is what I mean by the problem only happens "sometimes". Suppose A is having this kind of problem, and I start web server (tomcat or WAS) and I go access A for the first time if the problem occurs it will occur throughout the time of this server start-up. If the problem doesn't occur the first time I access A then throughout the time of this server start-up the problem wont occur. Also if this time it's the first resource not injected then it will be the same for this start-up.
Here is a bit of my application setup:
I use XML inter-mixed with annotation scanning. Basically all Action, Service, Dao classes are defined in XML however all property definitions are left out for Spring to scan the actual class.
Sample definition:
Code:
<!-- have this in all XML files -->
<context:annotation-config/>
<!-- an action definition, all actions are scoped prototype. It will use adm.common.admBranchesManager in the action with field annotated with #Resource -->
<bean id="adm.common.chooseBranchAction" class="com.bi.wms.adm.common.web.ChooseBranchAction" scope="prototype"></bean>
<!-- all service and dao are singleton and do not have any problem, all service/Manager are annotated with #Transactional. In Action we only code against interface and not actual concrete class -->
<bean id="adm.common.admBranchesManager" class="com.bi.wms.adm.common.service.impl.AdmBranchesManagerImpl"/>
<bean id="adm.common.admBranchesDao" class="com.bi.wms.adm.common.dao.jdbc.AdmBranchesDaoImpl"/>
Also for all actions they all extends an abstract action that has a resource field that's session-scoped.
Code:
<bean id="base.wms.login" class="com.bi.wms.common.model.WmsLogin" destroy-method="logout" scope="session">
<aop:scoped-proxy />
<property name="admUserSessionsManager" ref="adm.operation.admUserSessionsManager"/>
</bean>
Here is a part of a sample action:
Code:
//this class is just a sample not the actually one thats having the problem, AbstractWmsAction is the class that have a session-scoped bean
public class AdmWmsControlAction extends AbstractWmsAction
{
#Resource(name = "adm.operation.admWmsBatchGroupsManager")
private AdmWmsBatchGroupsManager admWmsBatchGroupsManager;
#Resource(name = "adm.operation.admWmsControlManager")
private AdmWmsControlManager admWmsControlManager;
//sometimes we use setters for injecting but that doesnt stop the problem from happening
//....omit
}
Don't know if anyone had this kind of issue.
If additional information is needed, I will do my best to provide.
Thanks
I've seen similar issues before with Spring using annotations. Which is why I prefer to use #Transactional in limited situations. Which classes are annotated with #Transactional? The implementation or the interface?
I've only looked at this quickly through the debugger, but I think you may be ending up with multiple beans, one Spring proxy created with the #Transactional -- ly annotated class, and the other defined in your application context. I would suggest that if you are defining the service in the Spring configuration file, you also define the transactional proxy there as well, and inject the proxy by name with your #Resource annotation, OR remove the configuration in xml, and inject by type in your annotation. This way, you'll be notified by Spring if you have duplicate matches by type that cannot be resolved.
to make a note here
after these time I have not found the real cause and solution.
However, time has proven that upgrading to Spring 2.3.3 or later solves the problem or at least the problem has not appeared yet
I'm working on a very small application connecting to a MySQL database.
I'm trying to create table record but getting 'no transaction in progress'.
I have all the right stuff in place:
a service interface MyService and its implementation MyServiceImpl
I have annotated the service impl with #Service
In the controller I used the interface name for the field #Autowired MyService
I have the correct transaction configuration as it was originally generated by roo
There is a public method MyService.create(...) which MyServiceImpl implements
But,
When I remote debug and inspect the controller's myService field what I see is something like
com.some.package.services.MyService#12345 (and NOT something like $Proxy73) which to me is not right, because what should be autowired is the proxy not he target bean (which is what I think this is). If I'm correct then it makes sense that there is no transaction as the annotation would only kick in when invoking a public method annotated with #Transactional on a proxy.
Please tell me why is spring injecting the target bean in this setup.
Thanks
If you have AspectJ-enabled transaction management (<tx:annotation-driven mode="aspectj" .../>) application of transactions happens in-place in the same class, either during build (compile-time weaving) or on startup (load-time weaving).
No new classes are created (like when using cglib) and no proxies (like with ordinary interface-based AOP in Spring). Instead bytecode of MyServiceImpl was modified directly without you even noticing. Unfortunately the only way to see AOP is to decompile your classes. If you use javap -c MyServiceImpl you'll find plenty of references to Spring transaction layer.
If you are using Spring MVC, make sure to scan specific controller classes alone in servlet context file. Otherwise it will scan 2 times and transaction is not available on the application context.