Spring #Transactional persist method not working - java

I have a Spring MVC sample application it uses UserDaoImpl class to save a User type object to database. Following is the UserDaoImpl code.
public class UserDaoImpl implements UserDao<User> {
private EntityManagerFactory emf;
#PersistenceContext
private EntityManager em;
#Transactional
public void saveUser(User user){
em.persist(user);
}
}
and my UserDao interface looks like this.
public interface UserDao<User> {
public void saveUser(User user);
}
Weird thing is happening when when my UserDaoImpl class implements the UserDao interface. When trying to persist it gives the following error.
java.lang.ClassCastException: $Proxy71 cannot be cast to org.samith.UserDaoImpl
When I remove the "implements UserDao" part from the UserDaoImpl class user is persisted to database as expected.
Also I tried UserDao interface without User parameter(that is non generic version). Still above error occurs.
This may be a trivial question to answer but I am scratching my head finding a solution for about few hours.
What wrong am I doing ??

You're not providing the problem code, (or the full stack trace) but the rundown is this:
When you annotate a class as #Transactional, and Spring creates an instance for you, what you get is not that class, but a Java Dynamic Proxy that implements that classes' interfaces. http://download.oracle.com/javase/1.3/docs/guide/reflection/proxy.html
Because of this, you cannot cast that object to the original type (it's not that type anymore!) and must use it's interface(s) instead.
If there aren't interfaces to implement, it will give you a CGLib proxy of the class, which is basically just a runtime modified version of your class, and so is assignable to the class itself.
Search for where you're injecting, or casting to type UserDaoImpl, and change the reference to UserDao instead, and it will work properly.
I've read the performance difference between CGLib proxies and Dynamic Java Proxies is quite minimal, so you can also add the following to your spring config to force it to use CGLib proxies instead of Java Dynamic Proxies:
<aop:config proxy-target-class="true">
In general however, I'd recommend you not use CGLib Proxies, but instead access your class from its interface. Loose coupling will allow you to do runtime substitution, and limits your ability to accidentally introduce brittle class dependencies.
There are some problems that using Java Dynamic Proxies will introduce however, and what you're doing is close enough to what I was doing that you should be aware of this:
How to use Dynamic Proxies with JSF when the method signature contains Object ... args

<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
worked for me too. the point was proxy-target-class="true" thanks to owner of the accepted answer. But then cglib dependency will be needed.

Related

How can I do CRUD operations through CrudRepository in Spring?

I'm working with PostgresSQL and I have the following interface:
#Repository
public interface ExampleRepository extends CrudRepository<ExampleEntity, Long> { }
Then I try to get the bean:
ExampleRepository repository = ctx.getBean(ExampleRepository.class);
Of course, I can't do that, because there's no implementation and eventually I get
NoSuchBeanDefinitionException: No qualifying bean of type 'ExampleRepository'
I know this is a wrong approach, but since I'm not enough experienced, I've got no idea how I can communicate with my database. Any example I searched only explained how to implement services & controllers in order to interact with db through Browser. But I want to do CRUD operation inside the java code.
Could anyone explain it to me? Any related sources would also be fine.
I am not sure how you are getting context (ctx) here.
But the common approach is #Repository is not needed instead, #EnableJPARepositories should be used in the #Configuration file. Then use #Autowired to inject the repository into your service class (where you want to execute operation from your repository bean)
You can refer below link for more details
https://mkyong.com/spring-boot/spring-boot-spring-data-jpa/
You don't need to create bean. It will created by the spring framework because you annotated your interface as #Repository .You need only #Autowired in your service class or where do you want to use this reference.
#Autowired
private ExampleRepository exampleRepository;

Why Spring's #Transactional works without proxy?

I got interested in how Spring's #Transactional works internally, but everywhere I read about it there's a concept of proxy. Proxies are supposed to be autowired in place of real bean and "decorate" base method with additional transaction handling methods.
The theory is quite clear to me and makes perfect sense so I tried to check how it works in action.
I created a Spring Boot application with a basic controller and service layers and marked one method with #Transactional annotation. Service looks like this:
public class TestService implements ITestService {
#PersistenceContext
EntityManager entityManager;
#Transactional
public void doSomething() {
System.out.println("Service...");
entityManager.persist(new TestEntity("XYZ"));
}}
Controller calls the service:
public class TestController {
#Autowired
ITestService testService;
#PostMapping("/doSomething")
public ResponseEntity addHero() {
testService.doSomething();
System.out.println(Proxy.isProxyClass(testService.getClass()));
System.out.println(testService);
return new ResponseEntity(HttpStatus.OK);
}}
The whole thing works, new entity is persisted to the DB but the whole point of my concern is the output:
Service...
false
com.example.demo.TestService#7fb48179
It seems that the service class was injected explicitly instead of proxy class. Not only "isProxy" returns false, but also the class output ("com.example.demo.TestService#7fb48179") suggests its not a proxy.
Could you please help me out with that? Why wasn't the proxy injected, and how does it even work without proxy? Is there any way I can "force" it to be proxied, and if so - why the proxy is not injected by default by Spring ?
There's not much to be added, this is a really simple app. Application properties are nothing fancy either :
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=superSecretPassword
spring.datasource.url=jdbc:mysql://localhost:3306/heroes?serverTimezone=UTC
spring.jpa.hibernate.ddl-auto=create-drop
Thank you in advance!
Your understanding is correct, but your test is flawed:
When the spring docs say "proxy", they are referring to the pattern, not a particular implementation. Spring supports various strategies for creating proxy objects. One of these is the java.lang.reflect.Proxy you tested for, but by default spring uses a more advanced technique that generates a new class definition at runtime that subclasses the actual implementation class of the service (and overrides all methods to apply transaction advice). You can see this in action by checking testService.getClass(), which will refer to that generated class, or by halting execution in a debugger, and inspecting the fields of targetService.
The reason that toString() refers to the original object is that the proxy implements toString() by delegating to its target object, which uses its class name to build the String.

The bean could not be injected as a 'Type' because it is a JDK dynamic proxy that implements: reactor.fn.Consumer

My Spring 4 application, which uses Reactor 2, fails to start with:
***************************
APPLICATION FAILED TO START
***************************
Description:
The bean 'orderHandlerConsumer' could not be injected as a 'fm.data.repository.OrderHandlerConsumer' because it is a JDK dynamic proxy that implements:
reactor.fn.Consumer
Action:
Consider injecting the bean as one of its interfaces or forcing the use of CGLib-based proxies by setting proxyTargetClass=true on #EnableAsync and/or #EnableCaching.
The OrderHandlerConsumer is really simple:
#Service
#Order(Ordered.HIGHEST_PRECEDENCE)
public class OrderHandlerConsumer implements Consumer<Event<OrderEnvelope>> {
#Override
public void accept(Event<OrderEnvelope> event) {
event.getData().getLatch().countDown();
}
}
Any ideas what might be going awry?
In your application class file where you define it as Spring application, add underneath it.
#SpringBootApplication
#EnableCaching(proxyTargetClass = true)
While the accepted answer will solve this issue, I think it will be more appropriate for me to explain why appling proxyTargetClass = true will fix this.
First of all, Spring, as a framework, utilizes proxing in order to supply the bean with some extended functionality, such as declaritive transactions via #Transactional, or caching by the means of #Cacheable and e.t.c. There are, in general, 2 ways(*) Spring can create proxy on top of your bean:
Jdk dynamic proxing
CGLib proxing
Offical documentation on this, in case you are interested.
Spring can create jdk dynamic proxy of the bean (in case proxing is required for this bean of course) if original class of the bean implements at least one interface. So spring basically create another implementation of this interface at runtime with some additional logic on top of original class.
What is the problem: if the bean is proxied by the means of jdk dynamic proxing , then you cannot inject this bean via its original class. So something like this:
#SpringBootApplication
#EnableTransactionManagement(proxyTargetClass = false)
public class StackoverflowApplication {
#Autowired private SomeService service;
public static void main(String[] args) {
SpringApplication.run(StackoverflowApplication.class, args);
}
}
#Service
class SomeService implements SomeInterface {
#Override
#Transactional
public void handle() { }
}
interface SomeInterface {
void handle();
}
wont work. Why? Well, becuase #Transactional tells Spring that it needs to create proxy of SomeService at runtime, and within #EnableTransactionManagement I specifically asked Spring to make it by the means of jdk dynamic proxy - spring will succeed, since jdk dynamic proxy can be created, but the problem is at runtime there is not bean of type SomeService, there is only a bean of type SomeInterface (by the way, if you inject service here not by the class, but by the interface - it will work, I assume you understand the reason by reading explaination above).
Solution: by applying #EnableTransactionManagement(proxyTargetClass = true) (notice true value here) you force spring to create CGlib proxy (this rule is applicable only for beans that utilize declarative transaction management, i.e. via annotations). In case of CgLib proxing, Spring will try to extend the original class, and add additional functionality at runtime in the generated child class. And in this case injection by class will work - because the bean extends class SomeService, so
#Autowired
private SomeService someService;
will work perfectly fine. But, in general, if possible, inject bean by interface, not by class. In this case both Cglib and jdk dynamic proxy will work. So, be aware of proxing mechanisms spring can use. Hope it helped, have a nice day.
You can assign a bean name to your OrderHandlerConsumer class so that Autowire resolution will be easier, Moreover, Instead of Autowiring with the concrete class, try to auto-wire with the interface. So that you can change #Service annotation to,
#Service(value="orderHandlerConsumer")
and try to Autowire with the interface type,
#Autowire
reactor.fn.Consumer orderHandlerConsumer;
Please try autowiring as below
class Test{
#Autowired
private Consumer orderHandlerConsumer;
}
If the target object to be proxied implements at least one interface
then a JDK dynamic proxy will be used. All of the interfaces
implemented by the target type will be proxied. If the target object
does not implement any interfaces then a CGLIB proxy will be created.
https://docs.spring.io/spring-framework/docs/3.0.0.M3/reference/html/ch08s06.html
You can call it two ways.
1st way is without mentioning the proxy [with default proxy], you can Autowire it by the interface like below.
#Autowired
private Consumer orderHandlerConsumer;
Spring AOP will create an instance for OrderHandlerConsumer.
2nd way is, mention the proxy in the bean as ScopedProxyMode.TARGET_CLASS.
then you can Autowire an instance without the interface [based on the class].
#Service
#Order(Ordered.HIGHEST_PRECEDENCE)
#Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class OrderHandlerConsumer implements Consumer<Event<OrderEnvelope>> {
#Override
public void accept(Event<OrderEnvelope> event) {
event.getData().getLatch().countDown();
}
}
and Autowire by the class like below.
#Autowired
private OrderHandlerConsumer orderHandlerConsumer;

Spring Security ACL - #PreAuthorize Generics & Interface

Using Spring ACL with #PreAuthorize annotations on Interfaces which use Generics does not seem to work.
Eg; I have an interface using generics;
public interface MyService<T> {
#PreAuthorize("hasPermission(#objectToProtect, 'WRITE')")
void doStuff(T objectToProtect, UserIdentity... user);
}
And an implementation;
public class MyServiceImpl implements MyService<MyObject> {
#Override
public synchronized void doStuff(MyObject objectToProtect, UserIdentity... userIdentity) {
// Do some stuff here... THis should be protected, the authenticated user should have write permissions.
}
}
I can see that PrePostAnnotationSecurityMetadataSource is picking up the annotations on the implementation, however it looks like its getting lost in the AOP passing further up and its never used when the acutal method is called. It works if I add the annotation to the concrete implementation (i.e. on the doStuff method in MyServiceImpl).
If I dont use generics in my interface and use something like Object it seems to work fine too. So is this a bug in Spring/Spring Security ACL or can we not use generics and expect them to be proxied.
My Spring config for the annotations looks like this;
<sec:global-method-security pre-post-annotations="enabled" proxy-target-class="true">
<sec:expression-handler ref="expressionHandler" />
</sec:global-method-security>
I'm using the latest GA version of Spring (3.2.3) and Spring Security (3.1.4)
There is open bug in spring Jira: https://jira.spring.io/browse/SPR-16060

How to declare a DAO variable using an interface but put in it a concrete implementation in Spring Framework?

I am studying how to integrate Spring Framework with Hibernate and I have some doubt about it.
I have develop a personal example that work well but I am not sure about the architecture of this project.
So I have an interface named PersonDAO in wich I have declared the CRUD operation that I would in my DAO
Then I have created a concrete implementation of this interface by the class PersonDAOImpl that implement the previous interface.
Then I have create the following main class to test my dao object:
package org.andrea.myexample.HibernateOnSpring;
import org.andrea.myexample.HibernateOnSpring.dao.PersonDAOImpl;
import org.andrea.myexample.HibernateOnSpring.entity.Person;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main( String[] args ){
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
System.out.println("Contesto recuperato: " + context);
Person persona1 = new Person();
persona1.setFirstname("Pippo");
persona1.setLastname("Blabla");
persona1.setPid(1);
System.out.println("Creato persona1: " + persona1);
PersonDAOImpl dao = (PersonDAOImpl) context.getBean("personDAOImpl");
System.out.println("Creato dao object: " + dao);
dao.addPerson(persona1);
System.out.println("persona1 salvata nel database");
}
}
The DAO work well and my object is correctly persisted on my database but I have the following architectural doubt: Why have I an interface if I am not using it?
Finnally, in this way, I could not have the interface and use directly the concrete class...
I think that, architecturally, this is so bad...
I have try to change my App.java clas and try to use the DAO object in this way:
PersonDAO dao = (PersonDAO) context.getBean("personDAOImpl");
but don't work...
In this tutorial: http://viralpatel.net/blogs/spring3-mvc-hibernate-maven-tutorial-eclipse-example/
there is an other situation, that really use the interface, in witch there is a ContactServiceImpl class in witch I have the ContactDAO variable declared using the #Autowired annotation:
#Autowired
private ContactDAO contactDAO;
ContactDAO is a DAO interface but Spring autowire an object that is an istance of it's implemtantio ContactDAOImpl (that is annoted using #Repository)
So, using the **#Autowired annotation, in this code I can declare a variable using an interface but put in this variable the reference to a concrete implementation of it !!!
In my project I don't use the annotion bean configuration mechanism but I am using the XML configuration mechanism...but I think that also in this case I can do somenthing like it...
I my project XML configuration file I have declared my bean like this:
<bean id="personDAOImpl" class="org.andrea.myexample.HibernateOnSpring.dao.PersonDAOImpl" >
<property name="sessionFactory" ref="sessionFactory" />
</bean>
What can I do to declare my dao variable as an interface and put in it a concrete implementation of it? (still using XML configuration)
This is the stack trace error that I have when I use:
PersonDAO dao = (PersonDAO) context.getBean("personDAOImpl");
in my App.Java test class
INFO: Using DataSource [org.apache.commons.dbcp.BasicDataSource#7363c839] of Hibernate SessionFactory for HibernateTransactionManager
Contesto recuperato: org.springframework.context.support.ClassPathXmlApplicationContext#591f5ff9: startup date [Sat Feb 23 11:42:25 CET 2013]; root of context hierarchyException in thread "main"
Creato persona1: org.andrea.myexample.HibernateOnSpring.entity.Person#23653628
java.lang.ClassCastException: org.andrea.myexample.HibernateOnSpring.dao.PersonDAOImpl$$EnhancerByCGLIB$$d46b3a86 cannot be cast to org.andrea.myexample.HibernateOnSpring.dao.PersonDAO
at org.andrea.myexample.HibernateOnSpring.App.main(App.java:27)
Tnx
Andrea
The very essence of interface and concrete implementation is to preserve polymorphism. In a testing environment you could use a different concrete implementation but same interface, while in developing mode another implementation could be put in the xml configuration. It would be easily for you to swap xml configurations without changing the java code like swapping from developing to testing environment or another tester would use your same code but with different xml configurations.
if you are going to use directly the implementation in the xml, then you will lose the power of polymorphism, and would need to change the java code if you have to swap to a different implementation.
Your PersonDAOImpl must implement PersonDAO, such as
public class PersonDAOImpl implements PersonDAO
Xml configuration is only use for dependency injection or singleton bean instances across the application, it doesn't have anything to do with preserving polymorphism. What you have to do is to follow the interface-implementation of java.
Where is the code for PersonDAOImpl? it must implement PersonDAO interface

Categories