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.
Related
I am trying to understand purpose of Spring-created beans. Are they just global shared object (such that they are declared like
#Component
public class MySpringBean{},
and later this object is used anywhere like inside some class
public class MyClass {
#Autowired
MySpringBean mySpringBean;
}
)?
Can their internal creation/implementation assumed like this? -
public class MyApp {
MySpringBean mySpringBean;
}
and used in MyClass like -
public class MyClass {
MySpringBean mySpringBean = MyApp.mySpringBean;
}
Its the object valid for only that class hierarchy. In your case Spring just create an object for mySpringBean and will keep it available for MyClass. Internally its more like
MySpringBean mySpringBean = new MySpringBean()
But actually
all Spring beans are managed - they "live" inside a container, called "application context".
Autowiring happens by placing an instance of one bean into the desired field in an instance of another bean. Both classes should be beans, i.e. they should be defined to live in the application context.
so in your case both mySpringBean and an instance of MyClass will be in application context.
Based on your question, I believe you should know about how beans are managed by Spring (or how Spring manages the life cycle of beans from initialization to destroy). But also note that you don't have to go into too much of details (wells, it's a framework that's is providing you). Yes, it's definitely true to init involves using new operator. These objects live inside the Container and Spring wires them whenever it's called for. Since beans are managed by Spring, you can implement callback methods too.
Given having next classes:
XRepository with declared a constructor with 1 argument (simple one,
not autowired), it has some autowired fields.
XService that uses XRepository as autowired.
XProcessor uses XService as autowired.
So I have to init XProcessor on runtime for specific value that will be used in XRepository constructor. On different calls I will have different arguments, so the injection should be on runtime.
Any idea how to achieve that using code configuration or annotations?
Remember that Spring needs to inject all the constructor parameters of Spring managed beans.
I believe you have two options:
Parse your URL info in controller and pass it through parameters down to persistence layer. This would be my preferred mechanism. You can create special DTO for passing various information down and keep your method signatures concise.
Your situation can alos be solved with request scope bean. You will
create one bean like this:
#Component
#Scope("request")
public class {
private String urlPart;
}
And you would autowire this component into XProcessor and
XRepository. Each request to your application will create new
instance of XRequestContext and you will parse your info in
XProcessor and store it into XRequestContext.
In XRepository you will use instance of XRequestContext to
retrieve information you stored in XProcessor.
You can read about request scope in Spring docs. It is like
ThreadLocal per request thread.
I have some legacy code where the class is a Spring bean defined and initialized through xml. It is a singleton with a field member which is a class dependency. There is a setter method for it, so I am assuming its supposed to be set via Spring, although I didn't find any xml defining it. There is also a get() method for the dependency, it has a null check and if its null it manually creates it outside of Spring like so
Class Test{
Dependency d;
setD(Dependency d){this.d=d;}
getD(){
if(this.d==null){
this.d = new Dependency();
}return this.d
}
}
I am trying to understand why this Spring bean is initializing a dependency outside of Spring and what are the implications if any, is this just bad/old design? or Am I not understanding something with how Spring works.
I would say it's a bad design, probably author wanted to provide fall-back for the case when D was not injected in spring. Another idea is an attempt to make D a lazy dependency. You should explore what's inside D.
Generally you can use #Required to mark the members that always should be injected. Or just use simple and nice constructor injection. If you're concerned about lazy injection, that's how Spring works by default.
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()
Is there a way to auto-cast Spring beans to the class defined in the application context XML? I'd like to avoid putting type information about the beans in 2 places.... in the xml configuration file and also in the code as a cast.
For instance, given this config file
<bean id="bean-name" class="SimpleSpringBean" scope="prototype">
<property name="myValue" value="simple value"></property>
</bean>
Can I call ApplicationContext.getBean("bean-name") in such a way as to avoid directly casting the return type to SimpleStringBean. I know I can also call ApplicationContext.getBean("bean-name", SimpleSpringBean.class) to avoid the cast itself, but I still have the type info in 2 places.
It seems that Spring can get the class info (ApplicationContext.getType) or by getting the type from the bean itself, but no way to automatically cast the type without programmer intervention.
I agree with Sii, you should avoid calling getBean as much as you can. Just wire your beans to classes that depends on them.
Still, if you have a single class that holds the application context, you can provide a wrapper generic method like the following:
class MyContextHolder{
ApplicationContext appContext;
......
#SuppressWarnings("unchecked")
public static <T> T getBean(String beanName)
{
return (T)appContext.getBean(beanName);
}
}
Then you can call it without casting
MyClass mc = MyContextHolder.getBean("myClassBean");
The answer is you shouldn't be using ApplicationContext.getBean() at all if it's possible, and bear with the one place you have to in the bootstrap code. (Generally, you should never need to use getBean() outside of your application's entry points.)
Also, what you're asking is likely impossible in the Java language at all. Casting is a compile-time feature, combined with a runtime check. The return type of getBean() simply must be known at compile time. Even if Spring can determine the type of an object, it can't change its own method signatures at runtime.
Another thing is that even if this were possible, the feature wouldn't be all that useful. Because Spring AOP is implemented using dynamic proxies, you nearly always want Spring to hand you an instance of an interface the bean implements (which could be an AOP proxy), not of the implementation class.
Another approach I also use is autowiring the bootstrapping class using:
public class Main {
#Autowired FooFacade foo;
#Autowired BarFacade bar;
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("appCtx.xml");
AutowireCapableBeanFactory bf = ctx.getAutowireCapableBeanFactory();
Object main = bf.createBean(Main.class,
AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT,
false);
((Main) main).run();
}
private void run() {
foo.doBootstrapStuff();
bar.doMoreBootstrapStuff();
}
}
(Code done from memory. Might only work if you have the Spring context configured to process wiring annotations, in that case making setters for foo and bar should work.)
The main reason for getBean being untyped is the compatibility of Spring (up to version 2.5.x) with Java 1.4. Spring 3.0 will drop that and thus offer typed getBean method then.
Nevertheless you should avoid looking up beans directly and minimize its usage as far as possible.
What if I use Spring as an object factory that my application uses extensively.
That is, instead of writing a bunch of classes that already inherit or wrap around
known Java classes I just decide to move all that into an xml file to cut down on
lines of Java code. This will mean many lines of xml but I won't need to make
skeleton Java classes which I inject with Spring or autowire. Thus making the lines
of Java code less.
For this reason and still as I am new to Spring I have just as stated in previous
posts used static Java methods which wrap around the getBeans().
I have worked with Spring but it is still new to me so forgive my question.
"Because Spring AOP is implemented using dynamic proxies, you nearly always want Spring to hand you an instance of an interface the bean implements (which could be an AOP proxy), not of the implementation class"
So there is no way to get a dynamic proxy using getBean(), then whats the best practice if there are no interfaces and its a stand alone driver class to be executed?