Lazy Initialization Exception inside static util method - java

I have a service:
#Override
#org.springframework.transaction.annotation.Transactional
public Seller doSomething(MyDto myDto) {
final MyObject myObject = myDao.findById(myDto.getId());
//do various things to myObject
StateChooser.calculateNewState(myObject);
}
In the implementation of calculateNewState, various LAZY collections are retrieved via an EAGER object:
public static void calculateNewState(MyObject myObject) {
List<MyOtherObject> otherObjects = myObject.getEagerObject().getMyLazyCollection();
//etc
myObject.setStatus(calculatedNewStatus);
}
But I get a Lazy Initialisation Exception on the call to getMyLazyCollection. This collection is an #ElementCollection, if that makes any difference.
I know that the object needs to be attached to the Hibernate session in order that the proxy can go to the database, but I don't understand how the object is becoming detached.
I have tried the following 'configurations' of the method calculateNewState:
static method of a util class (as in the example above) with no annotations
implemented in a #Component
with #Transactional
with #Transactional(PROPAGATION_MANDATORY)
without #Transactional
They all result in the same exception: "could not initialize proxy - no Session"
What am I doing wrong?
The aim of the calculateNewState method is to calculate the object's state before it is persisted to the database - I just want the logic to be shared so that it can be called from various different methods that change the object's data.
Edit
Just to clarify, the static method isn't annotated at all, and is only called from inside a method annotated with #Transaction. The object passed to the static method is loaded from a DAO inside the #Transaction method.

Related

Java constraint validation doesn't work for parameters [duplicate]

This question already has answers here:
Same class invoke NOT effective in Spring AOP cglib [duplicate]
(2 answers)
Closed 3 years ago.
I want use java bean validation annotations for parameters of my spring services. Consider following service:
public interface MyService {
void methodA();
void methodB(#NotBlank String param)
}
with implementation:
#Validated
public class MyServiceImpl implements MyService {
#Override
public void methodA() {
String param = "";
methodB(param)
}
#Override
public void methodB(#NotBlank String param) {
// some logic
}
}
Can you tell me how to fire validation and throw constraint exception when passed string is blank? When I call service this way:
#Autowired
MyService myService;
myService.methodB("");
When methodB is called from another class, a constraint exception is thrown as expected.
But when the same methodB ias called form MethodA, no exception is thrown. Why no exception is thrown, if the same method with the same parameter is called?
In addition to the other answers and the fact you are aware of the AOP proxies existance let me just point you to the relevant chapter in Spring documentation which mentiones self-invocation problem with AOP proxies that you've come across:
public class Main {
public static void main(String[] args) {
ProxyFactory factory = new ProxyFactory(new SimplePojo());
factory.addInterface(Pojo.class);
factory.addAdvice(new RetryAdvice());
Pojo pojo = (Pojo) factory.getProxy();
// this is a method call on the proxy!
pojo.foo();
}
}
fun main() {
val factory = ProxyFactory(SimplePojo())
factory.addInterface(Pojo::class.java)
factory.addAdvice(RetryAdvice())
val pojo = factory.proxy as Pojo
// this is a method call on the proxy!
pojo.foo()
}
The key thing to understand here is that the client code inside the main(..) method of the Main class has a reference to the proxy. This means that method calls on that object reference are calls on the proxy. As a result, the proxy can delegate to all of the interceptors (advice) that are relevant to that particular method call. However, once the call has finally reached the target object (the SimplePojo, reference in this case), any method calls that it may make on itself, such as this.bar() or this.foo(), are going to be invoked against the this reference, and not the proxy. This has important implications. It means that self-invocation is not going to result in the advice associated with a method invocation getting a chance to execute.
-- https://docs.spring.io/spring/docs/5.2.3.RELEASE/spring-framework-reference/core.html#aop-understanding-aop-proxies
In the next paragraph two solutions are proposed (or in fact three, but switching to AspectJ in this particular case might turn out cumbersome):
Okay, so what is to be done about this? The best approach (the term, “best,” is used loosely here) is to refactor your code such that the self-invocation does not happen. This does entail some work on your part, but it is the best, least-invasive approach. The next approach is absolutely horrendous, and we hesitate to point it out, precisely because it is so horrendous. You can (painful as it is to us) totally tie the logic within your class to Spring AOP, as the following example shows:
public class SimplePojo implements Pojo {
public void foo() {
// this works, but... gah!
((Pojo) AopContext.currentProxy()).bar();
}
public void bar() {
// some logic...
}
}
class SimplePojo : Pojo {
fun foo() {
// this works, but... gah!
(AopContext.currentProxy() as Pojo).bar()
}
fun bar() {
// some logic...
}
}
This totally couples your code to Spring AOP, and it makes the class itself aware of the fact that it is being used in an AOP context, which flies in the face of AOP. It also requires some additional configuration when the proxy is being created, as the following example shows:
public class Main {
public static void main(String[] args) {
ProxyFactory factory = new ProxyFactory(new SimplePojo());
factory.addInterface(Pojo.class);
factory.addAdvice(new RetryAdvice());
factory.setExposeProxy(true);
Pojo pojo = (Pojo) factory.getProxy();
// this is a method call on the proxy!
pojo.foo();
}
}
fun main() {
val factory = ProxyFactory(SimplePojo())
factory.addInterface(Pojo::class.java)
factory.addAdvice(RetryAdvice())
factory.isExposeProxy = true
val pojo = factory.proxy as Pojo
// this is a method call on the proxy!
pojo.foo()
}
Finally, it must be noted that AspectJ does not have this self-invocation issue because it is not a proxy-based AOP framework.
-- https://docs.spring.io/spring/docs/5.2.3.RELEASE/spring-framework-reference/core.html#aop-understanding-aop-proxies
Spring validation is invoked when a managed bean calls another managed bean.
However, spring context is unaware of calls between methods within the same bean, ie intrabean rather than interbean, so #Validation has no influence.
One simple solution is to move the wrapper method out of the class into a utility method, something like:
public static void methodA(MyService myService) {
myService.methodB("");
}
There is no annotation #Validation in Spring. I think you meant #Validated.
To validate parameters, Spring creates kind of proxy using CGLIB. This is mechanism similar to what Spring uses for transactions. Spring adds this code only if your class MyServiceImpl is called from another class, i.e. where a control flow crosses the border between two classes. When you call your methodB from another class, Spring adds validation code. When you call it from the same class, Spring adds no code and thus no validation is triggered.

Java design issue where behavior is attached to annotations

Let say I use JPA by using #transactions annotations.
So to have any method run under a transaction I add a #transaction annotations and BINGO my method run under a transaction.
To achieve the above we need have a interface for the class and the instance is managed by some container.
Also I should always call the method from interface reference so that the proxy object can start the transaction.
So My code will look like:
class Bar {
#Inject
private FooI foo;
...
void doWork() {
foo.methodThatRunUnderTx();
}
}
class FooImpl implements FooI {
#Override
#Transaction
public void methodThatRunUnderTx() {
// code run with jpa context and transaction open
}
}
interface FooI {
void methodThatRunUnderTx();
}
Well and Good
Now let say methodThatRunUnderTx does two logic operations
[1] call some service(long request/response cycle let say 5 sec) and fetch the results
[2] perform some jpa entity modifications
Now since this method call is long and we don't want to hold the transaction open for long time, so we change the code so that [2] happens in separate tx and methodThatRunUnderTx doesnt run in transaction
So we will remove the #Transaction from the methodThatRunUnderTx and add another method in class with #transaction let say new methods is methodThatRunUnderTx2, now to call this method from methodThatRunUnderTx we have to inject it into itself and add a method to interface so that the call happen through proxy object.
So now our code will look like:
class Bar {
#Inject
private FooI foo;
...
void doWork() {
foo.methodThatRunUnderTx();
}
}
class FooImpl implements FooI {
#Inject
private FooI self;
#Override
//#Transaction -- remove transaction from here
public void methodThatRunUnderTx() {
...
self.methodThatRunUnderTx2();// call through proxy object
}
#Override
#Transaction //add transaction from here
public void methodThatRunUnderTx2() {
// code run with jpa context and transaction open
}
}
interface FooI {
void methodThatRunUnderTx();
void methodThatRunUnderTx2();
}
NOW The Problem
We have made methodThatRunUnderTx2() to be public through interface.
But it is not what we want to expose as our api of FooI and not meant to be called from outside..
Any suggestion to solve it ?
That's why modern containers don't require any interface to be implemented - proxies are then created by dynamic subclassing or bytecode instrumentation is used.
So, the solution to your design issue is simple: Implement a helper class containing the transactional method and inject it to the class implementing the interface (and to any other class that can benefit from it).
Following the Interface Segregation Principle, separate the two logic operations into two interfaces: a fetcher and a modifier. Inject both into class Bar. This allows the two logic implementations to change independently of each other, for example allowing one to be transactional while the other is not. The second interface need not be a public class.
The question is a very valid one on handling the Transaction part. However, if you are trying to hide one functionality over other, you need to consider these :
OPTION 1 :
Considering - You would need to expose the method that does the whole functionality required by the caller
In this case of transaction handling, I would suggest you to keep the transaction open for the time being till it completes
OPTION 2:
Considering - You would need to efficiently manage transactions
Split the interface's methods based on Functionality IModifyFoo and ISelectFoo that does modify and select respectively and implement the methods and annotate with #Transactional on required methods
Interfaces are designed to be public that means that you need to be aware of what you need to expose to external world. In this scenario, you are posed to choose Principle over the technical challenge.
I can just think of these options and we are trying to address your technical challenge here that resides on basics of java. Good one to think about.
As you said, if you call a method on the same bean it'll not be proxied therefore no transaction management will happens, to solve it you can you Bean Managed Transaction where you manually start and stop the transaction:
class FooImpl implements FooI {
#Resource
private UserTransaction userTransaction;
#Override
//#Transaction -- remove transaction from here
public void methodThatRunUnderTx() {
...
self.methodThatRunUnderTx2();// call through proxy object
}
#Override
//#Transaction -- remove transaction from here too, because now you'll manage the transaction
public void methodThatRunUnderTx2() {
userTransaction.start();
// code run with jpa context and transaction open
userTransaction.commit(); // Commit or rollback do all the handling, i'm not writing it because its just an example
}
}
That way you are not exposing anything extra to public api, but you'll have a little extra code to manage the transaction.
if you want that methodThatRunUnderTx2 does not become public make it a private method and remove #Override annotation and remove it from interface.
You have to accept that transaction-based annotations won't work on private methods. So you simply cannot hide (make private) a method that is supposed to be a subject of that kind of annotation.
You can get rid of interfaces (i.e. #LocalBean in EJB world), but still, you cannot use private method...
For sure the solution for this problem are acpects. They would allow to get rid of self.methodThatRunUnderTx2() method call from the body of public void methodThatRunUnderTx(). Most probably the answer for this question could help you: Aspectj and catching private or inner methods
I'm not sure however if aspects are not too big gun for this problem, as they increase complexity and readability of code. I would rather think about changing architecture of your code in such a way, that your problem would not matter.

Can we mock a method in service while testing the service itself?

I am working on a project where I am using MyBatis annotations as persistence framework. Therefore, I have to create an interface for the 'mapper' and compose the mapper in the service like :
class XYZServiceImpl{
public XYZMapper getXYZMapper(){
return SessionUtil.getSqlSession().getMapper(XYZMapper.class)
}
}
Now while unit testing the service with Mockito, I am trying to inject a mock for the mapper. But since I am injecting mock in an instance of XYZService, how can mock a method of the service itself, in this case getXYZMapper() is what I am trying to stub. Although I have got a solution of creating the instance XYZMapper in the service and not call on demand like the above code does something like :
Class XYZServiceImpl{
XYZMapper mapper;
public void useXYZMapper(){
mapper = SessionUtil.getSqlSession().getMapper(XYZMapper.class);
}
}
But that would bring a lot of code changes (ofcourse I can refactor) but is there a way to achieve without having to make code changes?
Also what would be a 'purist' way to have a mapper instance in the class is it the method 1 that is better than method 2 in terms of performance?
EDIT : Here XYZMapper is an interface. Something like :
public interface XYZMapper{
#Select("SELECT * FROM someclass WHERE id = #{id}")
public SomeClass getSomeClass(int id);
}
EDIT : I am facing a similar situation but with a variance that I have a service that I do want to test like XYZServiceImpl. Now it has a method getXYZDetails() which has a lot of business logic handled within the service. Now if getXYZDetails looks like the following :
public XYZDetails getXYZDetails(int id){
XYZDetails details = new XYZDetails();
details.set1Details(fetchSet1Details(id));
//Perform some business logic
details.set2Details(fetchSet2Details(id));
if(details.set2Details() != null){
for(int i = 0; i < details.set2Details().size(); i++){
flushTheseDetails(i);
}
}
.
.
}
Kindly notice that fetchSet1Details(), fetchSet2Details(), flushTheseDetails are public service, public and private service respectively.
I want to know of a method that can mock/stub these methods while testing getXYZDetails() thus enabling me to
There are several options you can use.
Inject dependency
This works only for simple methods like getXYZMapper when method only returns external dependency of you object. This may require to create new XYZServiceImpl instances if for example mapper is bound to connection which is opened per request.
Encapsulate method behavior in object
Another way to achieve similar result is to use a factory or service locator
like this:
public class XYZServiceImpl {
public XYZServiceImpl(XYZMapperFactory mapperFactory) {
this.mapperFactory = mapperFactory;
}
public XYZMapper getXYZMapper() {
return mapperFactory.getMapper();
}
}
This will allow you easily substitute factory in test with implementation which returns mock mapper.
The similar approach can be used for other methods fetchSet1Details, fetchSet2Details, flushTheseDetails that is moving them to other class or classes. If the method contains complex (and may be loosely related) logic it is a good candidate to be moved in separate class. Think about what these methods do. Usually you can move some essential and unrelated part of them to other class or classes and this makes mocking them much easier.
Subclass
This is not recommended but in legacy code sometimes is very helpful as a temporary solution.
In your test subclass you class under test and override methods you need:
#Test
public void someTest() {
XYZServiceImpl sut = new XYZServiceImpl() {
public XYZMapper getXYZMapper() {
return mapperMock;
}
public Whatever fetchSet1Details() {
return whateverYouNeedInTest;
}
}
sut.invokeMethodUnderTest();
}
The only thing you may need to do is to change access modifier of private method to package-private or protected so you can override them.
Spying
This method in also discouraged but you can use mockito spies:
XYZServiceImpl realService = new XYZServiceImpl();
XYZServiceImpl spy = Mockito.spy(realService);
when(spy.fetchSet1Details()).thenReturn(whaeveryouneed);
when(spy.getXYZMapper()).thenReturn(mockMapper);
spy.methodUnderTest();
I would suggest the "purist" way of doing this is to accept an XYZMapper instance in your constructor and store it in a local field.
In production use, you can pass an e.g. SQLXYZMapper, which will interact with your database. In test use, you can pass in a mocked object that you can verify interactions with.

spring singleton bean fields are not populated

I need a service (singleton fits) with some internal fields, like a list of pending threads (yes everything is written to be thread safe) the problem is that if I #autowire this bean, fields appear to be empty. Debugging I see that the proxy correctly binds to the instance (fields CGLIB$CALLBACK_X are correctly linked to the populated bean) with populated fields, but the fields it offers are empty.
The following lines of codes give a general idea of what i'm talking about.
#Service
public class myService{
#Autowired
private Monitor monitor;
public List getSomething(){
return monitor.getList();
}
}
#Service
public class myStatefulService{
//This field will be populated for sure by someone before getSomething() is called
private List list;
public synchronized List getSomething(){
return this.list;
}
//Called by other services that self inject this bean
public synchronized void addToList(Object o){
this.list.add(o);
}
}
Debugging the variable monitor during the getList call I get
monitor => instance of correct class
fields:
CGLIB$BOUND => true
CGLIB$CALLBACK_0.advised => proxyFactory (correct)
CGLIB$CALLBACK_1.target (reference to the correct instance of myStatefulService class)
fields:
list => [.........] (correctly populated)
CGLIB$CALLBACK_2 .....
......
......
......
list => [] (the list that would be populated is empty instead)
Are you curious or you have some real issue? Nevertheless here is an explanation.
When using CGLIB to proxy classes Spring will create a subclass called something like myService$EnhancerByCGLIB. This enhanced class will override some if not all of your business methods to apply cross-cutting concerns around your actual code.
Here comes the real surprise. This extra subclass does not call super methods of the base class. Instead it creates second instance of myService and delegates to it. This means you have two objects now: your real object and CGLIB enhanced object pointing to (wrapping) it.
The enhanced class is just a dummy proxy. It still has the same fields as your base class (inherited from it) but they are not used. When you call addToList() on myService$EnhancerByCGLIB object it will first apply some AOP logic, call addToList() of myService (which it wraps) and apply remaining AOP logic on return. The myService$EnhancerByCGLIB.list field is never touched.
Why can't Spring use the same class and delegate via super? I guess for simplicity: first create "raw" bean and then apply AOP proxying during post-processing.
"This field will be populated for sure by someone before getSomething() is called"
By someone? No, the Spring bean factory. If you don't configure it, nothing will be populated.
Not every bean needs to be under Spring's control. It sounds like you want to have a List that clients can add and remove items to in a thread-safe way. If that's true, remove the #Autowired annotation, create a new List, and expose methods to add and remove.
I'd recommend a List from the new concurrent collections.
CGLIB will proxy protected getters.
So you can have:
#Autowired
private Monitor monitor;
protected Monitor getMonitor() { return monitor; }
public List getSomething(){
return getMonitor().getList();
}
getMonitor() will be proxied to call getMonitor() on the other instance which has monitor injected.

Unit testing Spring 3 database methods

I have abstract class that defines database methods, such as inserts and updates, and a concrete class that implements it. The database configurations (dataSource, DatabaseTarget etc) are defined as beans in context.xml-file.
The database with its methods work in Controller when I'm using Spring 3 anotations by
private AbsractClass a;
Constructor:
#Autowired
public Controller(AbstractClass a) {
this.a =a;
}
...and a getter for a.
Calling database methods is done by
getA().insertValues();
But I would like to write Junit tests for my methods. Is there any example for this kind of situation? I have googled for hours.
If you want to test your controller methods without touching the database (which is the correct way), create a new class that extends the AbsractClass and pass it as argument to your Controller class, example:
CustomerController controller= new CustomerController(new InMemoryCustomerDao());
//call your actions and assert, all calls to the database will hit the InMemoryDao.
Another way is to use a Mock Object if you don't want to create extra fake classes in your project or you need to assert that these arguments are being correctly called.

Categories