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.
Related
I have this code:
How could I make the use of the getService() method mandatory in the getAll methode, that means if I call directly service.findAll() compilation fails ?
Is it possible to create an annotation to prohibit the directly use of the field ?
#Named
#Profile("default")
public class AlfrescoVersionServiceImpl {
#Inject
//Request Scope service
private AlfrescoService service;
#Resource
private WebServiceContext webServiceContext;
public List<Fichier> getAll(){
return getService().findAll();
}
public AlfrescoService getService(){
service.setEnPointAdress("--");
if(webServiceContext.isUserInRole(role)){
service.setRole("--");
}
}
}
Thank you in advance for your reply.
You could move the service field into a super class, and declare it private to prevent the subclass from accessing it, while leaving getService() protected.
Alternatively, you could configure the AlfrescoService in a #Produces method, so everyone asking for an AlfrescoService to be injected gets an instance that has already been configured.
Inside findAll() you could examine the current stack trace using Thread.getStackTrace() and make sure the previous StackTraceElement is the class and method you want:
public List<Fichier> findAll() {
StackTraceElement[] stack = Thread.getStackTrace();
if(stack.length > 1) {
// stack[0] is ourselves, stack[1] is who called us
if(stack[1].getClassName().equals(...) && stack[1].getMethodName().equals(...) {
// execute the business logic
}
}
}
Just beware of a few things:
This is a runtime check, so methods calling findAll() won't be flagged at compile time.
According to the JavaDocs, the getStackTrace() method may not be permitted by some SecurityManagers, and some VMs may omit stack frames in rare cases.
This may not be performant if you do this for every request.
If the service is a Spring bean, you may have to deal with sorting through proxy classes to find the real caller (i.e. the previous stack frame before findAll() may be a spring generated proxy class).
An alternative would be to use an Aspect Oriented framework. For example, Spring AOP has the ControlFlowPointcut that can be used to match caller name, class, and package. This approach is a little more declarative,
but relies on an extra library.
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.
This is possibly a really easy question, but it's something that's not entirely clear to me.
I have a bean as follows:
#Singleton
#Startup
#Lock(READ)
public class SomeDataBean {
List<Foo> foos;
#PostConstruct
public void init() {
// Build foos;
}
public List<Foo> getFoos() {
return foos;
}
#Lock(WRITE)
public void modifyFoos() {
// This could be potentially called too
}
}
Subsequently, this bean is injected (using CDI - environment is Wildfly 8.2), into various other beans (Request/Session/View etc.) Now they all access this list of Foos. My question is, is it safe to return the list as is, when potentially modifyFoos() could be invoked by another bean. Or is this something that will never happen and is guaranteed by the container?
I've read some of the docs on the container managed transactions etc, but it's not entirely clear how it works in situations such as this. Is it better here to replace list with a concurrent container for example?
No, it is not safe, because a thread can read the list while another thread modifies it.
Return a copy of the list (not efficient if there are many reads).
Use copy-on-write list.
Store a new instance of the list in modifyFoos.
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.
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.