Spring AOP: around advice without calling proceed - spring

I have application managed by Spring v4. I'd like to user AOP to add logging without code change but.. Generally I have tow component managed by Spring one is used for creating second one, let's call them A and B. During crating A method B.initialize is being called. To log the start of initializing I have Aspect component with appropriate pointut:
#Around("execution(* com.aop.B.initialize())")
So my problem: method initialize has a few nullable properties which will be initialized in the future with another framework so when I call proceed() the result is NullPointerException, but... when I comment proceed method and pointcut method are invoked everything works fine. Result is two records in log (those which should be before and after proceed method) and well initialized component A.
Could somebody explain me what happened here? I mean, does Around advice without direct proceed invoking works in the same way ans the Before one?

Related

Creating Spring Beans with arguments only known at runtime

I have a class that requires parameters provided by the user at runtime. I do this because I like the idea of ensuring the object is always in a valid, ready to use state. However I do not know the parameter values until the user has started using the application which is causing problems with Spring IoC as everything is instantiated at start up.
I think I can work around it this with #Configuration, .getBean calls with arguments, and #Lazy annotations however it feels like I'm kluging (eg. .getBean calls are discouraged)
Is there a nicer way to handle this? I'm thinking I should just lump it and move to having a constructor with no parameters and force a setter method call with the parameters but then I'll have an object sitting around that's in an invalid state.

getting bean id of target class in advice

I have a few classes that interact with databases (more than one). Some classes are reused so for example "obs.table1" is used to interact with table1 in database "obs" while "ref.table1" is used to interact with table1 in database "ref". These databases are at different URLs and each gets its own connection pool, etc... obs.table1 and ref.table1 are both instances of MyTable1Class, defined in beans file.
I have a pointcut that intercepts calls to methods annotated with #Transactional or with a custom annotation #MyTablesAnnotation and have it set so those calls will all get routed into a #Around advice.
This all works and the flow through the advice is correct.
What I am trying to add is reporting on what is going on in there. Currently I can tell where in there I am, but I can't tell if it was obs.table1 or ref.table1 object that got me there.
Is there a way to extract the bean id of the object on whose method the advice was invoked on?
ProceedingJoinPoint that is passed to the method the only thing I do with it is call a .proceed on it and the rest is just various checks and catches. I see that I can get either the target class or proxy class out of it, but... not sure how to go from there to knowing what the bean id was.
Is it possible?
Firstly it is not recommended to depend on bean id as it creates tight coupling with framework.
To quote from docs Note that it is not usually recommended that an object depend on its bean name, as this represents a potentially brittle dependence on external configuration, as well as a possibly unnecessary dependence on a Spring API.
Now to answer your question yes it is possible to fetch the name of bean via org.springframework.beans.factory.BeanNameAware.
The class for which you require the bean name should implement it and spring will auto-magically inject the name of the bean. However there is a gotcha which you should be aware and is mentioned in docs here

Do Spring transactions propagate through new instantiations

I'm working on a bunch of legacy code written by people before me and I'm confused about a particular kind of setup and wonder if this has ever worked to begin with.
There is a managed bean in spring that has a transactional method.
#Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Throwable.class)
public boolean updateDraftAndLivePublicationUsingFastDocumentsOfMySite(List<FastDocumentLite> fastDocumentLites, Long mySiteId) throws Exception { ... }
Now inside that method I find new instantiations calling update methods fe:
boolean firstFeed = new MySiteIdUpdate(publishing, siteDao, siteDomainService).update(siteId, fastDocumentLites.get(0).getMySiteId());
From my understanding on IOC this new class isn't managed by spring , it's just a variable in the bean. Now going further inside the update method you see another service gets called.
#Transactional(propagation=Propagation.REQUIRED, rollbackFor=Throwable.class)
public void activateSubdomainForSite(Long siteId, boolean activationOfSite)
So if there is a transaction open it should be propagated into this service. But here is what I don't get if that MySiteIdUpdate object isn't managed by spring does the first transaction move forward to the activateSubdomainForSite method ?? Or is another transaction being opened here. I looked in the logs and I believe it to be the latter but I rather ask the experts for a second oppinion before I proclame this legacy code to be complete rubbish to the project lead. I'm suffering with a StaleStateException somewhere further down the road and I'm hoping this has anything to do with it.
I think the code is correct, and the second #Transactional should reuse the existing transaction.
Because:
1) Spring Transaction handling is done either by Proxies or by AspectJ advices. If it is done by Proxies then it is required that MySiteIdUpdate invoke an instance that is injected (this is what you did). If you use AspectJ, then it should work anyway.
2) The association Transactions to the code that use is done by the Thread, this mean, as long as you "are" in the thread which started the transaction you can use it. (you do not start an new thread, so it should work)
An other way to explain: It is perfect legal when you have some method in your call hierarchy that does not belong to an spring bean. This should not make the transaction handling fail.

jsf 2 spring application logging specific events

I have an JSF2 app which uses Spring for transactions,security and DI container.
The application has 3 layers :
1. JSF view + JSF Managed Bean
2. Service classes
3. DAO classes
So, a request is something like:
JSF Page -> JSF MB -> Service class -> DAO Class -> DB, and the the other way around.
My problem is that there are service methods that after perform their business had to log to DB that event.
For instance, when someone activates/deactivates a user. I want to log this action along with the user id.
So, I only see two approaches here : (I`m sure there are more)
1. inside this method I determine the logged in user and perform the actual logging
- as i disadvantages here I would see the fact that this method will be not so easy to test, because of the userId picked from SpringSecurity
2. Using SpringAOP. This way would be noninvasive, which is cool, but then I would have an aspect for one method, which is not so efficient.
I would like to know if you guys had this kind of issues and if so, how did you solve them ?
Consider introducing a marker annotation. Let's call it: #LogEvent. Then annotate every method you wish to intercept. This way you can implement a single aspect with an advice that matches not on naming convention but on the presence of #LogEvent.
something like:
#After("execution(#LogEvent * *.*(..))")

Spring Data JPA save() throws NPE

I wrote a web service with spring boot using spring data jpa for persistence.
The webservice has some static objects (in Singleton Bean) that regulary needs to be backed up to my database.
Sometimes! (This sucks...I dont' really know what happens) when I call
ObjectType updated = myRepository.save(existingObject)
I get an java.lang.NullPointerException - without usable stacktrace as the method doing this is running via #Scheduled.
I tried debugging and existingObject seems to be absolutely fine. The error only occurs, when existingObject is actually NOT a new object (i.e. when id != 0)
P.S. I am using Spring Boot therefore not really using EntityManager. I only use the #Autowired myRepository.
I'm seeing something similar happening. During save, it seems the object is re-fetched from DB (perhaps to see which fields were altered?) but a ManyToOne relationship is not loaded (even though the FetchType is explicitly set to EAGER).
For some reason, a compareTo is called on the relationship. The related object isn't null, but it only has its ID filled in (presumably because that was available in the object that was fetched from the DB). All other fields are null.
When the compareTo then does its stuff, a NullPointerException follows.
As to the actual solution, I don't know yet, as I would have expected the FetchType EAGER to make sure the relationship is loaded. Hopefully this helps someone to further find the root cause.
(I would have added this as a comment as it doesn't actually answer the question, but StackOverflow won't let me due to insufficient reputation...)
You haven't provided enough information. IF that line is where the NullPointerException is occurring, then the only possibilities are that myRepository is null, or existingObject is null. However, it's possible the NullPointerException is happening as a result of something in the save. Wrap the code in a try catch, and log the exception stacktrace to file.
If needed, checkout the logging customization notes here:
http://projects.spring.io/spring-boot/docs/spring-boot/README.html

Resources