Why is PostConstruct not called? - java

I am working on a simple Java EE application.
I have class like this:
import javax.annotation.PostConstruct;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
#Stateless
public class BlogEntryDao {
EntityManager em;
#PostConstruct
public void initialize(){
EntityManagerFactory emf = Persistence.createEntityManagerFactory("Persistence");
em = emf.createEntityManager();
}
public void addNewEntry(){
Blogentry blogentry = new Blogentry();
blogentry.setTitle("Test");
blogentry.setContent("asdfasfas");
em.persist(blogentry);
}
}
So my managed bean calls this method. Until here no problems. But since the initialize method is not called, I am getting an NPE in em.persist.
Why is the initialize method not being called? I am running this on Glassfish server.
Regards.

The Java EE bean annotations such as #PostConstruct only apply to container-managed beans. If you are simply calling new BlogEntryDao yourself, the container isn't going to intercept the creation and call the #PostConstruct method.
(Furthermore, you'd be better off using #PersistenceContext or #PersistenceUnit instead of manually fetching the EntityManagerFactory in your initialize() method, and you should be creating an EntityManager for each call to addNewEntry(), since they're short-lived. Making these changes would eliminate the need for initialize() at all.)

I had the same problem in my application.
You didn't post your bean context configuration xml file (so I'm not sure if it's the same issue) but in my case adding this line:
<context:annotation-config/>
Solved my problem.
You need either <context:annotation-config/> or <context:component-scan/> to enable #PostConstruct annotation.

Since this question comes up first on Google for "postconstruct not called", another reason a #PostConstruct method might not be called besides using the new keyword instead of putting #PostConstruct in a Spring bean is if you have a circular dependency.
If this bean were to depend on another bean that depended on this bean, your other bean might call addNewEntry() before BlogEntryDao was initialized, even though BlogEntryDao is a dependency for that other bean.
This is because Spring didn't know which bean you wanted to load first due to the circular reference. In this case, one can remove the circular reference or use #AutoWired/#Value constructor parameters instead of member values or setters, or if using xml configuration, maybe you can swap the order in which the beans are defined.

In my case #PostConstruct was not called because my initialize() method was static and was also throwing an exception. In either case the method is ignored. I hope it helps someone else who made the same mistake.
This can be found in the console:
WARNING: JSF1044: Method '<XXX>' marked with the 'javax.annotation.PostConstruct' annotation cannot be static. This method will be ignored.
WARNING: JSF1047: Method '<XXX>' marked with the 'javax.annotation.PostConstruct' annotation cannot declare any checked exceptions. This method will be ignored.

When using Spring make sure you are using the right PostConstruct annotation from the right package.
javax.annotation.PostConstruct
should be the one. Not for example:
jakarta.annotation.PostConstruct
It took me a little while to figure out why only one of my PostConstruct didn't work.

In my case #PostConstruct method was not called because I was referencing to a public instance variable of the spring service bean directly in other service beans (ie myService.myProperty). When i made a public getter method for the property (ie getMyProperty()) and used that to get the property the #PostConstruct method was called again. Also I made myProperty private to prevent any accidental direct referencing in the future.
Also note that if you don't explicitly register the class with #Bean in a #Configuration annotated class and rely soley on #Autowired instead, the #PostConstruct method may not be executed immediately on startup. Only when one of the methods of the autowired class are referenced and called by another class will that class be loaded and only at that time will the #PostConstruct method be called. In other words, by only using #Autowired you are essentially lazy loading a class. If you want to load it at startup, register it with #Bean
Heres a good SO thread about the difference between #Bean and #Autowired Difference between #Bean and #Autowired
EDIT: One last remark. When you have a webapplication and decided to annotate your class with #RequestScope then the #Postconstruct annotated method will be called each time when a new request comes in. This is because #RequestScope instructs spring to create a new instance of the class every time a new request comes in. If you want all requests to use the same instance, then you could use #Bean as mentioned above, but you could also use the annotation #Singleton above your class. This will cause the class to be loaded eagerly upon startup.

Make sure the class having #Postconstruct method lies within the same package. I moved class file to main package and it worked.

In my case I had two instances of javax.annotation.PostConstruct inside classpath. One was bundled with the war package and another was provided by tomcat. When Spring is scanning for the #PostConstruct annotation it compares these two different instances. Therefore the #PostConstruct annotated method was not picked while scanning.
Providing only one instance of javax.annotation-api library solved the issue.

Since most of the ways are already mentioned. However one can also create a bean in the config file for the class
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor
;
This will enable PostConstruct and PreDestroy annotations.
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"></bean>
Also for Predestroy one needs to call context.registerShutDownHook()

Related

Inheritance with SqsListener

I have a strange situation that I don't understand.
I would like to decide in a bean, should I enable or disable the SQS listener.
So I've created a config class with a definition:
#Bean
MyListener createListener(Features f){
return f.shouldListen() ? new RealListener() : new MockListener();
}
As you can see, I have such an inheritance:
interface MyListener{}
class RealListener implements MyListener{
#SqsListener(...)
list handleMessage(SqsMessage message){
...
}
}
class MockListener implements MyListener{}
Now, the funny part:
It sometimes works.
After few restarts of the application, the handleMessage() method is called but in most cases it isn't without any exception. The queue is created, all permissions are in place.
To make it working I need to return RealListener from createListener() method or move #SqsListener annotation to a method in the MyListener interface. Both are not options for me, because I don't want to call AWS, when the mock is enabled.
I've tried with conditional bean creation but as Features depends on a DB (indirect entityManager dependency, to be more precise), I can't make it working. I've tried with abstract class instead of interface, but without luck. I've tried to register the RealListener bean in the BeanFactoryPostProcessor but this also doesn't work (same entityManager dependency issue). I've tried to move the annotation to the interface and use #ConditionalOnBean with #Primary to create an empty AmazonSqsClient when the mock is enabled, but it doesn't work.
I could understand that it doesn't work, because the bean has to be created for a type with the method annotated with #SqsListener (not with it's supperclass/interface type), but I have three such beans and a lottery - sometimes all work, sometimes one or two but sometimes none of those.
Do you have any suggestions?
Well... I've found the issue but it still would be nice, to know, what has happened.
So... There is a class QueueMessageHandler using detectHandlerMethods(...) method from the superclass AbstractMethodMessageHandler. This method uses MethodIntrospector.selectMethods() to select methods to scan. This class takes into consideration methods annotated with #SqsListener when there is #EnableSqs in some configuration class.
The problem is, in my project the #EnableSqs annotation is located in some file - not the file with createListener(...) method and not the main class of the Spring Boot application. That means, the class with #EnableSqs can be loaded before or after MethodIntrospector.selectMethods().
The output is:
I have no idea, why it works fine without inheritance and doesn't work with inheritance
To fix the issue, I've moved #EnableSqs to the main class of the project

Accessing spring bean proxy reference itself

I have an issue with #Cacheable and #CacheEviction annotations. When I call these methods in the bean where they are declared, the aop part is not getting executed.
The underlying reason for this is that the bean access to its own instance itself, instead of accessing the spring proxy.
I have read this question where it is said that in most cases it should not be necessary a bean accessing the proxy.
Probably those answers work for me. The question is:
Is there any other way to make annotated methods work? Or does it sound like I found a good reason for a bean needing to access the proxy itself?
As is well documented in the Spring user manual, self-invocation cannot work with Spring AOP because Spring AOP uses proxies. So if you want to make self-invocation trigger an aspect, please switch to full AspectJ via LTW (load-time weaving). It works with the original beans and does not use any proxies.
Update: If you want to avoid using native AspectJ and instead as a (pretty lame and anti-AOP) workaround want to make your component proxy-aware, of course you can use self-injection and reference the cached method using the auto-wired proxy like this:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
#Component
public class MyComponent {
#Autowired
MyComponent myComponent;
public void doSomething() {
System.out.println(myComponent.doCacheable());
System.out.println(myComponent.doCacheable());
System.out.println(myComponent.doCacheable());
}
#Cacheable("myCache")
public String doCacheable() {
return "" + System.nanoTime();
}
}
Calling doSomething() on the MyComponent bean should yield output like this:
247760543178800
247760543178800
247760543178800
This proves that caching works like this. If instead you just have three lines of either System.out.println(doCacheable()); or the weird, nonsensical variant from the other (now deleted) answer
System.out.println(MyComponent.this.doCacheable());, then you would get three different values on the console, i.e. nothing would be cached.

How to call Spring Framework repositories methods

I know that there are questions similar to this one, but none of them have helped me. I'm following along this tutorial, and the part I can't wrap my mind around is:
#SpringBootApplication
public class Application {
private static final Logger log =
LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
#Bean
public CommandLineRunner demo(CustomerRepository repository) {
return (args) -> {
// save a couple of customers
...
// more lines, etc...
What I don't understand is where the repository passed into demo comes from. I know that the Autowired annotation can do something like that, but it isn't used at all here.
The more specific reason I ask is because I'm trying to adapt what they do here to an application I'm working on. I have a class, separate from all of the persistence/repository stuff, and I want to call repository methods like save and findAll. The issue is that the repository is an interface, so I can't instantiate an object of it to call the methods. So do I have to make a new class that implements the interface and create an object of that? Or is there an easier way using annotations?
When creating a #Bean, adding the repository in the parameters of the bean is enough to wire the repos in your bean. This works pretty much like adding #Autowired annotation inside a class that is annotated as #Component or something similar.
Spring works mostly with interface, since that is simplier to wire vs wiring concrete classes.
Can you try #Repository before the declaration of class? Worked for me in a Spring MVC structure.
#Repository
public class EntityDAOImpl implements EntityDAO{
...
}
The thing to wrap your head around is a Spring Boot application at startup time aims to resolve its dependancy tree. This means discovering and instantiating Beans that the application defines, and those are classes annotated with #Service, #Repository, etc.
This means the default constructor (or the one marked with #Autowire) of all beans is invoked, and after all beans have been constructed the application starts to run.
Where the #Bean annotation comes into play is if you have a bean which does not know the values of it's constructor parameters at compile time (e.g. if you want to wire in a "started at" timestamp): then you would define a class with an #Configuration annotation on it, and expose an #Bean method in it, which would return your bean and have parameters that are the beans dependencies. In it you would invoke the beans constructor and return the bean.
Now, if you want a certain method of some class to be invoked after the application is resolved, you can implement the CommandLineRunner interface, or you can annotate a method with #PostConstruct.
Some useful links / references:
https://docs.spring.io/spring-javaconfig/docs/1.0.0.m3/reference/html/creating-bean-definitions.html
https://www.baeldung.com/spring-inject-prototype-bean-into-singleton
Running code after Spring Boot starts
Execute method on startup in Spring

Issue in calling DAO method from Service

I have a DAO that has method like this:
class AbcService
{
private AbcDAO isntance;
public void getStuff()
{
instance.getQueryResult();
}
}
Now if this method is called from anywhere it will give a NullPointerException where instance calls the query method.
Still this code is in use in the project from a long time and i would think twice before calling it incorrect. Is there some way by which this code can be accessed. Is this a standard practice?
If you have a setter for isntance, you just need to call it before calling getStuff. This is standard (although some would say all needed fields should be set inside a constructor.
This answer just applies if you are using springbean and its broader than your question.. But I guess this will be useful to you
Yes this is generally used practice when you are using it as a spring bean. So, before calling this method, you need to be sure that this springbean is instantiated. Basically, this is done by either getting spring bean from ApplicationContext or the caller class itself receives instance of this bean from its parent bean....
General practise is to load application context by defining contextloaderlistener in web.xml. For more info on how to do it, see http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/web/context/ContextLoaderListener.html
I think the object instance is injected to AbcService via the Spring Dependency Injection. Please search for any ".xml" file in your project, which has fully qualified class name of AbcService mentioned in its bean definition.

Spring #Value annotation always evaluating as null?

So, I have a simple properties file with the following entries:
my.value=123
another.value=hello world
This properties file is being loaded using a PropertyPlaceHolderConfigurer, which references the properties file above.
I have the following class, for which I'm trying to load these properties in to like so:
public class Config
{
#Value("${my.value}")
private String mValue;
#Value("${another.value}")
private String mAnotherValue;
// More below...
}
The problem is that, mValue and mAnotherValue are ALWAYS null... yet in my Controllers, the value is being loaded just fine. What gives?
If instances of Config are being instantiated manually via new, then Spring isn't getting involved, and so the annotations will be ignored.
If you can't change your code to make Spring instantiate the bean (maybe using a prototype-scoped bean), then the other option is to use Spring's load-time classloader weaving functionality (see docs). This is some low-level AOP which allows you to instantiate objects as you normally would, but Spring will pass them through the application context to get them wired up, configured, initialized, etc.
It doesn't work on all platforms, though, so read the above documentation link to see if it'll work for you.
I had similar issues but was a newbie to Spring.
I was trying to load properties into an #Service, and tried to use #Value to retrieve the property value with...
#Autowired
public #Value("#{myProperties['myValue']}") String myValue;
I spend a whole day trying various combinations of annotations, but it always returned null.
In the end the answer as always is obvious after the fact.
1) make sure Spring is scanning your class for annotations by including the package hierachy
In your servlet.xml (it will scan everything below the base value you insert.
2) Make sure you are NOT 'new'ing the class that you just told Spring to look at. Instead, you use #Autowire in the #Controller class.
Everything in Spring is a Singleton, and what was happening was Spring loaded the values into its Singleton, then I had 'new'ed another instance of the class which did not contain the newly loaded values so it was always null.
Instead in the #Controller use...
#Autowired
private MyService service;
Debugging...
One thing I did to find this was to extend my Service as follows...
#Service
public class MyService implements InitializingBean
Then put in debug statements in...
#Override
public void afterPropertiesSet() throws Exception {
// TODO Auto-generated method stub
LOGGER.debug("property myValue:" + myValue);
}
Here I could see the value being set on initialization, and later when I printed it in a method it was null, so this was a good clue for me that it was not the same instance.
Another clue to this error was that Tomcat complained of Timeouts trying to read from the Socket with Unable to parse HTTPheader... This was because Spring had created an instance of the service and so had I, so my one was doing the real work, and Spring was timing out on its instance.
See my answer here.
I ran into the same symptoms (#Value-annotated fields being null) but with a different underlying issue:
import com.google.api.client.util.Value;
Ensure that you are importing the correct #Value annotation class! Especially with the convenience of IDEs nowadays, this is a VERY easy mistake to make (I am using IntelliJ, and if you auto-import too quickly without reading WHAT you are auto-importing, you might waste a few hours like I did).
The correct import is:
org.springframework.beans.factory.annotation.Value
As its working with #Controller, it seems you are instantiating Config yourself. Let the Spring instantiate it.
You can also make your properties private, make sure your class is a Spring bean using #Service or #Component annotations so it always gets instantiated and finally add setter methods annotated with #Value . This ensures your properties will be assigned the values specified in your application.properties or yml config files.
#Service
public class Config {
private static String myProperty;
private static String myOtherProperty;
#Value("${my.value}")
public void setMyProperty(String myValue) {
this.myProperty = myValue;}
#Value("${other.value}")
public void setMyOtherProperty(String otherValue) {
this.myOtherProperty = otherValue;}
//rest of your code...
}
Add <context:spring-configured /> to you application context file.
Then add the #Configurable annotation to Config class.
In my case in my unit test, executeScenarioRequest always is null
#RunWith(SpringRunner.class)
#ExtendWith(MockitoExtension.class)
class ScenarioServiceTestOld {
#Value("classpath:scenario/SampleScenario.json")
Resource executeScenarioRequest;
Change #ExtendWith(MockitoExtension.class) to #ExtendWith(SpringExtension.class)

Categories

Resources