#PostConstruct fails silently on a Grails Service - spring

I thought the Spring annotations were supposed to work out of the box in a Grails environment, but I cannot get it to work at all. I also tried the afterProperties method, which did not work either.
Can anyone spot a mistake? Is there some configuration I need to do?
package dashboard
import javax.annotation.PostConstruct
class EmailJobSchedulerService
{
def grailsApplication
#PostConstruct
def init() {
def cronExpression = grailsApplication.config.emailAt8AmTrigger
println(cronExpression)
EmailSubscribersJob.schedule(cronExpression, new HashMap())
}
}

Try changing it to
#PostConstruct
void init() {
(i.e. void instead of def). I'm not sure whether Spring specifically enforces this but the specification of #PostConstruct states that among other things "The return type of the method MUST be void".
Edit: uchamp's comment is correct, I just tried the same test and indeed the #PostConstruct annotated method is called only the first time the service bean is used and, not necessarily immediately at startup. You can add
static lazyInit = false
to the service class to force it to be initialized eagerly at startup. This doesn't appear to be documented in the user guide, I deduced it by reading the code.
Note that "used" in the previous paragraph doesn't necessarily mean you have to call a method on it. The service bean will be initialized the first time it is fetched from the application context, either directly or because it has been autowired into another bean that is being initialized. For example, injecting the service into BootStrap using
def emailJobSchedulerService
would be enough to fire the #PostConstruct method, you don't have to actually call any of the service's methods from the BootStrap.init closure. Similarly, if your service were injected into any controllers then the init would fire the first time one of those controllers handled a request (any request, it doesn't have to be an action that calls the service).

Just adding on the answer from #Ian - For some reason i had:
#PostConstruct
private void init() {
This also failed silently and gave strange behavior. Solution was to remove "private":
#PostConstruct
void init() {

Related

How to use #Autowired correctly in spring boot standalone app

I've learned a lot recently about Spring and one thing i think i might be misunderstanding is the #Autowired annotation, especially when using it in constructors. You see, the app i'm developing is a service so basically EVERYTHING is initialized within a constructor. The only actual user-driven events that happen are buttons that restart certain modules of the service. This is my main method :
ConfigurableApplicationContext ctx = new SpringApplicationBuilder(MDHIS_Service.class)
.headless(false).web(false).run(args);
java.awt.EventQueue.invokeLater(() ->
{
MDHIS_Service frame = ctx.getBean(MDHIS_Service.class);
frame.setSize(1024, 768);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
This is the constructor of my main class, where basically everything happens. I have omitted the calls to the methods initializing each module to shorten it :
#Autowired
public MDHIS_Service(GlobalParamService globalParamService, LogEntryService logentryService, InterfaceService interfaceService,
ConnectionService connectionService, OutboundMessageService outboundMessageService, OutboundMessageHistoryService outboundMessageHistoryService,
InboundMessageService inboundMessageService, FacilityService facilityService, ModuleStatusService moduleStatusService,
SequenceService sequenceService)
{
this.globalParamService = globalParamService;
this.logEntryService = logentryService;
this.interfaceService = interfaceService;
this.connectionService = connectionService;
this.outboundMessageService = outboundMessageService;
this.outboundMessageHistoryService = outboundMessageHistoryService;
this.inboundMessageService = inboundMessageService;
this.facilityService = facilityService;
this.moduleStatusService = moduleStatusService;
this.sequenceService = sequenceService;
}
My main class has a private final global variable for each service. Each module is a separate thread and i'm finding myself having to pass those variables to the constructor of each module which in term stores them into it own private final variables. The way i'm doing things right now #Autowired is pretty much useless since i'm having to pass the instance around. Is there a way to better use #Autowired? This service is used as the backend for a large web app and i find myself making much better use of the annotation in there. I did a lot of research on this topic and i did try the #PostContruct annotation but all i ever got was null services.
Any help would be appreciated.
Thanks!
I figured out my problem, and it was a pretty dumb one. First off, i had not annotated my main class with #Component so Spring never bothered to inject the dependencies in it. Secondly, I did not realize that a method annotated with #PostContruct would run by itself after the constructor runs WITHOUT NEEDING TO EXPLICITELY BE CALLED!
I moved all my initialization code to an init method annotated with #PostConstruct and annotated my main class with #Component, everything is working now!
You typicall don't have to use a constructor + #Autorwired, you can directly use autowired on fields and spring would fill the dependencies for you:
#Component
public class MDHIS_Service {
#Autowired
private GlobalParamService globalParamService;
}
What is important to understand is that for spring to work, you must let it create the objects for you, and not calling the constructors explicitely. It would then fill the dependencies as needed. This is done by declaring the service as a component (for example with the #Component annotation) and never create the service yourself but getting them from dependency injection.
The first object you start with has to have been created by spring and returned by the application context.
What you gain in exchange is that you don't have to forwared everything explicitely. A sub-sub-sub service quite distant from the root of the application can depend on anything it has visibility without you having to forward the reference all the way.
I would advise to take a look a the spring reference documentation, it quite detailled and complete:
https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#spring-core
Edit: I'll try to clarify a bit with an example... What do the init code of the various service actually does ?
Maybe it set the dependencies. Then just autowire them:
#Component
MySubService {
#Autowired MySubSubService mySubSubService;
}
Maybe it does some more thing than setting fields so you can add on top an init method that do it and this init method can eventually call the other services.
#Component
MySubService {
#Autowired MySubSubService mySubSubService;
#PostConstruct
public void init() {
//Init code that may use mySubSubService.
}
}
You don't have to declare a constructor and forward dependencies yourself, sprint does it for you.
The only case where you'd have problem is if finally you need some parameters that are not dependency to the init method. But even in that case you could do it from you main code. That's actually what you did with the main service calling the various setters rather than messing with the constructor to set theses values.

Testing methods in #Component class having #PostConstruct anotation

I am testing service methods that are placed in controllers in spring applications. It seems to me that my problem is that one essential service method call is done in class which is anotated #Component and the method call is inside #PostConstruct anotated method.
#Component
public final class Helper
#PostConstruct
public void initialize() {
stuff = service.getNessesaryStuff();
}
The contents of the stuff are coming from a database and they vary in each test. That's why database is populated with needed data before each test. Without the data the other service methods are not working. I have checked that the right data goes to database exactly like intended, but it does not affect right away. I need to run same test couple of times before it gets the right data and passes.
Any fix?
When running the application, Helper class is created itself. When running tests, I need to make a bean of it to avoid NullPointerExceptions.

Accessing Spring #Transactional service from multiple threads

I would like to know if the following is considered safe.
Usual Spring service class that accesses a bunch of DAOS / hibernate entities:
#Transactional
public class MyService {
...
public SomeObject readStuffFromDB(String key) {
...
//return some records from the DB via hibernate entity etc
}
A class in the application that has the service wired in:
public class ServiceHolder {
private MyService myService;
private SomeOtherObject multiThreadedMethod() {
...
//calls myService.readStuffFromDB() and uses the results
//to return something useful
}
multiThreadedMethod will be called from multiple threadpool threads. I would like to know if the multiThreadedMethod is safe in its calls to myService.
It is NOT making any modifications to the DB - only reading.
What happens if two threads call myService.readStuffFromDB() at exactly the same time? Will a concurrent modification exception be thrown from somewhere?
I've been running it with no issues but I'm not 100% sure it will always work.
Yes you will call the same object in the same time as long as your service bean is defined as singleton (which is default and proper), but you should not rely on local variables in you services. So the methods should be written that way they can work independently (you don't need a mutual exclusion here). If you called db and tried do any operations nothing would happen because every thread would receive a new instance of entity manager. If you modified db in the same time and any type of db exception was thrown you would get a rollback exception which is perfectly fine.
entityManager.persist() will do more or less entityManager.getEntityManagerAssignedToCurrentThread().persist()
It is a proxy not real object. So you are safe :)

Spring - How can I destroy my prototype-scoped beans?

I've got a singleton bean that has a method that creates instances of a prototype bean. I'm using the method documented here to get instances of the prototype bean.
public class SingletonService implements ApplicationContextAware {
private ApplicationContext applicationContext;
public void go() {
MyPrototypeBean prototype = applicationContext
.getBean(MyPrototypeBean.class);
prototype.doSomething();
}
#Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}
}
At first I thought that this was good enough, that my instance of 'prototype' would go out of scope when the 'go' method returned, meaning that the instance would have not reference and would be garbage collected.
However, a peer pointed out the following statement from the documentation:
The client code must clean up prototype-scoped objects and release
expensive resources that the prototype bean(s) are holding.
So it sounds like Spring will retain a reference, and so the gc will never pick it up? If that's the case how do I tell Spring to release the reference? The documentation mentions that I can use a 'custom bean post-processor', but it's not clear where that processor would fit in and what code it would run.
Thanks all in advance for helping out,
Roy
I think you're misunderstanding the documentation. It's just saying Spring won't manage the lifecycle of the prototype bean, so #PreDestroy (etc.) methods need to be called by your own code. Spring won't retain a reference.
Just to add some clarity to artbristol's answer above: artbristol is correct. Spring will create the prototype bean required by your code, but will not destroy it. This behaviour is by design as it is considered to be more effective to allow the garbage collector to 'pick up' your prototype dependency once it goes out of scope. If it was not done this way, then the only other alternative would be for Spring container to retain a reference to each and every instance of your prototype bean as they are created. Given that your code creates a NEW instance of MyPrototypeBean bean each time it is called, this means you could potentially have too many instances of MyPrototypeBean being generated, collecting but not being destroyed because destruction only occurs with the closing of the Spring Container. You can appreciate that this could very easily lead to a rapid memory leak.
As a result, it is by design that prototype beans are handled by the garbage collector, being destroyed as and when they go out of scope OR when their destruction methods are manually called.
What the documentation is saying is that IF MyPrototypeBean is holding onto any resources such as a database connection, then this will prevent that resource being properly released. It therefore becomes the coder's responsibility to manage this.

How can a test 'dirty' a spring application context?

The spring framework documentation states:
In the unlikely case that a test may
'dirty' the application context,
requiring reloading - for example, by
changing a bean definition or the
state of an application object -
Spring's testing support provides
mechanisms to cause the test fixture
to reload the configurations and
rebuild the application context before
executing the next test.
Can someone elaborate this? I am just not getting it. Examples would be nice.
Each JUnit test method is assumed to be isolated, that is does not have any side effects that could cause another test method to behave differently. This can be achieved by modifying the state of beans that are managed by spring.
For example, say you have a bean managed by spring of class MySpringBean which has a string property with a value of "string". The following test method testBeanString will have a different result depending if it is called before or after the method testModify.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations={"/base-context.xml"})
public class SpringTests {
#Autowired
private MySpringBean bean;
#Test public void testModify() {
// dirties the state of a managed bean
bean.setString("newSring");
}
#Test public void testBeanString() {
assertEquals("string", bean.getString());
}
}
use the #DirtiesContext annotation to indicate that the test method may change the state of spring managed beans.

Resources