Set object in application context in spring mvc - java

I have a utility class which I want to initialize when the application starts in Spring MVC. So I am implementing InitializingBean. Now I have to create an object for the same and save it in Application scope so that I can access the same instance everywhere. But I am not able to get hold of this.
Here is my try:
public class DashboardInitializer implements InitializingBean, ApplicationContextAware {
private ApplicationContext mApplication;
#Override
public void afterPropertiesSet() throws Exception {
initializeConfigurationUtil();
ConfigurationUtil util = ConfigurationUtil.getInstance();
/* Save the util to application scope */
}
#Override
public void setApplicationContext(ApplicationContext pApplication) throws BeansException {
this.mApplication = pApplication;
}
}
Is this approach correct or there is a better way to do that?

I think you need to simplify this a little bit.
You want the utility class to be initialized after your application context is loaded, but you also want your util class to be in the application context?
Seems the util class has some dependency objects configured in the application context, and the util class is in turn a dependency of some classes in the application context.
If you can express these dependencies in the form of beans (util is a bean, which has its dependency beans injected into it, and beans that need util have util injected into them), Spring will ensure that all dependencies of util are initialized first, then util is initialized and then it is injected into classes that need util.
You should not try to add something to an initialized context.. Its not possible.
If you cannot express util and its dependencies as beans, you can also take this approach:
1. Configure util as a bean in the application context, add a default constructor that does nothing. So this object would be created, but not initialized when the spring context is loaded.
In the ApplicationContextAware implementation you have, modify the setApplicationContext method. Get the util bean you configured earlier from the context.
You can now initialize (execute some code that you want to execute) the util instance, just make sure you do not try to reassign the bean to some other instance of util.
Hope this helps.

You can use #postconstruct annotation on methods to perform business logic immediately after the application has been initilized. And properties can simply be injected using placeholder in config and #Value annotation on java fields.

Related

java.lang.IllegalStateException: Cannot load configuration class : com.project.config

I have a spring core application. In which I have private constructors. while executing the application, it throws
java.lang.IllegalStateException: Cannot load configuration class
at the time of bean creation.
I searched over I found that, could be problem because of AOP, but I am not using AOP. What would be the problem.
private Demo() {
//private constructor.
}
You should make a public constructor in order spring framework can instantiate the bean, the other way you can do it is doing a public static factory method, but you will need to say to the spring framework, what uses this method in order to instantiate this bean.

Guice How to inject dependencies to an object instantiated from a dynamically loaded class

I want to load a plugin which is dependent to some features of my application.
I can create an instance of the entry class. Bu I cannot inject required dependencies to it.
For example lets assume that I have class in the plugin like that:
class ThirdPartyService implements Service {
//no argument constructor and overridden methods
//Inject database config which is known by application to the service:
#Inject
void setDatabaseConfig(DatabaseConfig dbConfig) {
this.dbConfig = dbConfig;
}
}
The guice modules in the application don't know ThirdParyService. Because it is a dynamically loaded class. So I cannot bind Service to this class. Is there any way to inject DatabaseConfig to a ThirdParyService instance?
Note: I don't want to load the plugins at the beginning of the application. Instead, I want to load plugins at runtime.
Use injector.injectMembers()
This will call the setter injection

What are the ways to get ApplicationContext object in Spring?

Hi i want to know what are the different ways to get ApplicationContext Object in Spring?
I know only one way that is,
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
is there any other ways? if it is please let me know.
Thanks.
You can also use annotation based configuration
#Configuration
public class Config {
#Bean
public Bean1 bean1() {
return new Bean1();
}
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class);
}
}
You can implement the interface ApplicationContextAware, like this :
public class MyClass implements ApplicationContextAware {
private ApplicationContext applicationContext;
#Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
}
If you are using annotation, you could also autowire it
#Autowired
private ApplicationContext applicationContext;
Also, the code you wrote does not get an existing application context, it creates one.
Well, there are a lot of ways out there, I wonder whom would know them all...
But first, we need to make a difference between instanting a new context, or getting a running and existing application-context.
By new ***ApplicationContext a new context will be created. Therefore all Subclasses of org.springframework.context.ApplicationContext can be used to create a new ApplicationContext. You can find all implementing classes here. The new way to instantiate a spring-context is through AnnotationConfigApplicationContext.
Also, you can add a displatcher-servlet or an servlet-listener in your web.xml. Or use a framework like gemini-blueprint in an osgi-environment which starts all xml-files in meta-inf/spring. (e.g. eclipse virgo)
On the other hand, you can get an existing context (which means not a new one) through different ways:
ApplicationContextAware
Implement the ApplicationContextAware interface and you will get the context via setApplicationContext(ApplicationContext applicationContext) method.
Just add #Autowired private ApplicationContext applicationContext; to your spring bean. But make sure it is a spring bean.
In your web-application, you can get the context of your listener-context via ApplicationContextUtils.getWebApplicationContext( servletcontext)
There would a lot of more ways, but these are those which popped up in my mind quickly.
If you are referring to the possible way you can create an ApplicationContext and not to the ways such an instance can be passed through your code then I suggest taking a look at the Spring javadoc for ApplicationContext. So based on this the concrete implementations of this interface are:
org.springframework.context.annotation.AnnotationConfigApplicationContext
Standalone application context, accepting annotated classes as input - in particular #Configuration-annotated classes, but also plain #Component types and JSR-330 compliant classes using javax.inject annotations. Allows for registering classes one by one using register(Class...) as well as for classpath scanning using scan(String...).
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
This is essentially the equivalent of AnnotationConfigApplicationContext for a web environment.
org.springframework.context.support.ClassPathXmlApplicationContext
Standalone XML application context, taking the context definition files from the class path, interpreting plain paths as class path resource names that include the package path (e.g. "mypackage/myresource.txt"). Useful for test harnesses as well as for application contexts embedded within JARs.
org.springframework.context.support.FileSystemXmlApplicationContext
Standalone XML application context, taking the context definition files from the file system or from URLs, interpreting plain paths as relative file system locations (e.g. "mydir/myfile.txt"). Useful for test harnesses as well as for standalone environments.
org.springframework.context.support.GenericApplicationContext
Generic ApplicationContext implementation that [...] does not assume a specific bean definition format
org.springframework.context.support.GenericXmlApplicationContext
Convenient application context with built-in XML support. This is a flexible alternative to ClassPathXmlApplicationContext and FileSystemXmlApplicationContext, to be configured via setters, with an eventual AbstractApplicationContext.refresh() call activating the context.
org.springframework.context.support.GenericGroovyApplicationContext
An ApplicationContext implementation that extends GenericApplicationContext. [...] Consider this as the equivalent of GenericXmlApplicationContext for Groovy bean definitions, or even an upgrade thereof since it seamlessly understands XML bean definition files as well.
org.springframework.web.context.support.GenericWebApplicationContext
Subclass of GenericApplicationContext, suitable for web environments.
org.springframework.web.context.support.GroovyWebApplicationContext
WebApplicationContext implementation which takes its configuration from Groovy bean definition scripts and/or XML files, as understood by an GroovyBeanDefinitionReader. This is essentially the equivalent of GenericGroovyApplicationContext for a web environment.
org.springframework.jca.context.ResourceAdapterApplicationContext
ApplicationContext implementation for a JCA ResourceAdapter. Needs to be initialized with the JCA BootstrapContext, passing it on to Spring-managed beans that implement BootstrapContextAware.
org.springframework.context.support.StaticApplicationContext
ApplicationContext implementation which supports programmatic registration of beans and messages, rather than reading bean definitions from external configuration sources. Mainly useful for testing.
org.springframework.web.portlet.context.StaticPortletApplicationContext
Static Portlet-based ApplicationContext implementation for testing. Not intended for use in production applications.
org.springframework.web.context.support.StaticWebApplicationContext
Static WebApplicationContext implementation for testing. Not intended for use in production applications.
org.springframework.web.portlet.context.XmlPortletApplicationContext
Portlet-based WebApplicationContext implementation which takes its configuration from XML documents, understood by an XmlBeanDefinitionReader.
org.springframework.web.context.support.XmlWebApplicationContext
WebApplicationContext implementation which takes its configuration from XML documents, understood by an XmlBeanDefinitionReader. This is essentially the equivalent of GenericXmlApplicationContext for a web environment.

Spring - creating objects with new operator using #Configurable & #Value annotations

Is it possible to use #Configurable on a class that's weaved using AspectJ and get Spring to load in values on fields/methods which are annotated with #Value?
I know its possible with #Autowired and #Resource etc... Are there any others.
e.g.
#Configurable
public Class MyObj{
#Value("$(my.prop)")
private String aField;
public String getAField(){
return aField;
}
}
And then have something like
public aMethodSomewhereElse(){
MyObj obj = new MyObj()
assertNotNull(obj.getAField());
}
Are there any alternatives to being able to create MyObj with the new operator and still get spring to handle the annotations?
--EDIT:--
It IS possible to do this using new when using #Autowired, have a look at some Hibernate and JPA stuff with Spring and AOP... I've used this in the past to do some profiling of Java code. But I really want to use SPEL and #Value before I mock up a full example I was hoping to find the answer here. FYI - if you don't belive me the Spring Manual even says it is possible to do this, what I want to know is if its possible to use #Value annotations in the same scope...
The Spring container instantiates and configures beans defined in your
application context. It is also possible to ask a bean factory to
configure a pre-existing object given the name of a bean definition
containing the configuration to be applied. The spring-aspects.jar
contains an annotation-driven aspect that exploits this capability to
allow dependency injection of any object.
And...
Using the annotation on its own does nothing of course. It is the
AnnotationBeanConfigurerAspect in spring-aspects.jar that acts on the
presence of the annotation. In essence the aspect says "after
returning from the initialization of a new object of a type annotated
with #Configurable, configure the newly created object using Spring in
accordance with the properties of the annotation". In this context,
initialization refers to newly instantiated objects (e.g., objects
instantiated with the 'new' operator) as well as to Serializable
objects that are undergoing deserialization (e.g., via readResolve()).
http://static.springsource.org/spring/docs/3.0.0.RC2/reference/html/ch07s08.html
Cheers.
You are absolutely right - #Autowired fields will be wired in an #Configurable annotated class even outside of a Spring container, assuming that you have a AspectJ infrastructure in place.
You have noted a good catch though, #Value fields are processed by a Spring bean post processor(AutowiredAnnotationBeanPostProcessor), which resolves the #Value annotated fields. It does not act on objects instantiated outside of the container though - so in short, the #Autowired fields should get wired in, but #Value properties will not.
Doing
MyObj obj = new MyObj()
means that obj is not managed by spring, so it will not do autowiring.
Only way to do that is to obtain instance from an application context. For example:
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
MyObj obj = context.getBean("myBean");
I don't think it is possible to use new operator and ask spring to autowire properties. I think 1 way to solve this is to get a static reference to applicationContext and create a prototype scoped bean.
#Component
public class ApplicationContextLocator {
private static ApplicationContext applicationContext;
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
public ApplicationContextLocator() {
super();
}
#Autowired
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ApplicationContextLocator.applicationContext = applicationContext;
}
}
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
#Component
public class MyObj {
.....
}
public aMethodSomewhereElse(){
MyObj obj = ApplicationContextLocator.getApplicationContext().getBean(MyObj.class)
assertNotNull(obj.getAField());
}

Using Spring-wired libraries with robotframework

I have an elaborate Spring bean setup for integration tests. Now I'm looking into writing a Robot library to expose my test data creation / behavior execution / assertion methods to Robot tests.
However what I understand from the Robot Framework user guide is that Robot can only instantiate library classes by calling a constructor. This is a bummer because I'd rather have my instances managed by Spring.
Ideally, I'd want to be able to give Robot the path to the application context and the bean name for the library. Failing that, I'd want Robot to be able to invoke a static factory method rather than a constructor, so I'm not forced to create a new instance.
One workaround I thought of is to create the Spring context in a static initializer and wire my dependencies by fetching beans from that context.
My original class looks like:
public class MyAwesomeTests {
#Autowired
private ThisHelper thisHelper;
#Autowired
private ThatHelper thatHelper;
// implementations of test steps and such
}
So I would change the above #Autowired fields to be protected, and create a subclass that statically initializes the Spring context and defines a Robot-friendly constructor:
public class RobotFriendlyTests extends MyAwesomeTests {
private static final ApplicationContext CONTEXT = new ClassPathXmlApplicationContext(...);
public RobotFriendlyTests() {
this.thisHelper = (ThisHelper) CONTEXT.getBean("thisHelper");
this.thatHelper = (ThatHelper) CONTEXT.getBean("thatHelper");
}
}
This should work, but it feels somewhat clunky. Is there a better way I should consider? Better yet, is there a Robot extension that already does this for me?
Have you thought about using Spring #Configurable, then even instances created by a normal new will become spring managed beans.
#See Spring Reference Chapter 7.8.1 Using AspectJ to dependency inject domain objects with Spring
There's a Robot Framework extension that supports using Spring to wire test libraries, take a look at: http://code.google.com/p/robotframework-javalibcore/wiki/SpringLibrary
I am not entirely sure whether it supports your case since I am not familiar at all with Spring.

Categories