Load application context without using web.xml - java

I was wondering if there's a way to Load Springs application context without having to define it in a web.xml.
I see you can use:
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
But if you wanted to use a bean you've got to getBean() to have access to it. I am thinking possibly there could be a way to load the context programmatically as would the definition in web xml, without having to call getBean.
Any ideas?

You can use:
ctx.getAutowireCapableBeanFactory().autowireBeanProperties(this,
AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
...where ctx is your ClassPathXmlApplicationContext to avoid the need to ever call getBean() - any spring bean fields on this will be autowired for you.

There is a way. You just have to read official documentation. The relevant part is here.
Edit: Sorry, misread your question. You can use
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
and load it using ServletContextListener at application startup. When your application starts, if you've configured your bean wiring properly, you shouldn't have to call getBean() to access all of your beans. Treat it like you're using Java SE.

Related

What is the proper way to have a "singleton" in Spring 4?

I have a java file "DatabaseMan.java" that helps connect to a database and connects helper functions. How can I make it such that it is created once for the life of my spring application, and I can call of its methods "getAllRows" for example, in each of my other resource classes?
Should I be declaring a bean in my Application.java or using some sort of annotation on my "DatabaseMan" class to indicate that it is "injectable"/"resusable"?
I see the following Spring3 example:
http://www.mkyong.com/spring3/spring-3-javaconfig-example/
The issue is, do I have to include this within every single resource:
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
HelloWorld obj = (HelloWorld) context.getBean("helloBean");
obj.printHelloWorld("Spring3 Java Config");
Is there a better way to get to the "HelloWorld" with less code and more annotation in Spring 4?
Remember, the ApplicationContext is a container to manage all your beans and their inter-dependencies. It is the entry point to your application. Once you've set it up, all the managed objects are linked up and ready to go.
Is there a better way to get to the "HelloWorld" with less code and more annotation in Spring 4?
It depends where you want to get it. If you want to get it from outside the ApplicationContext, then you need to do what you did. If you want to get into another bean, just inject it and the ApplicationContext will do the rest.
#Component
class SomeOtherBean {
#Autowired
private HelloWorld helloWorldBean;
// do something with it
}

Spring container implementations

I keep on learning Spring and it is very difficult to figure out which implementation of ApplicationContext is intended for. I've standalone J2EE application and I don't interested in Web* or Portlet* implementations.
Can you provide me the brief list of possibilities (if isn't clear, see P.S. section of my question) and purposes of each implementation below:
ResourceAdapterApplicationContext
StaticApplicationContext
ClassPathXmlApplicationContext
FileSystemApplicationContext
P.S.
A don't ask you to provide me reference to the docs. For example:
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
But from that definition its not clear that ClassPathXmlApplicationContext also implements AbstractRefreshableApplicationContext and can be used to change beans definition without stopping server.
I'm sorry you don't want references to the docs, but that's where all the information is.
StaticApplicationContext states
org.springframework.context.ApplicationContext implementation which
supports programmatic registration of beans and messages, rather than
reading bean definitions from external onfiguration sources. Mainly
useful for testing.
So you use it to register bean definitions directly
StaticApplicationContext context = new StaticApplicationContext();
context.registerBeanDefinition(beanName, beanDefinition);
This can be used in cases where your ApplicationContext needs to be dynamically changed. Note that you can pass a parent ApplicationContext to the StaticApplicationContext if you need both behaviors, ie. reading from XML/Java config and dynamically registering.
ClassPathXmlApplicationContext is one of the more common ApplicationContext implementations in my opinion. You simply point it to an XML (bean definition) resource on the classpath and it loads it up. The javadoc states
Useful for test harnesses as well as for application contexts embedded
within JARs.
You could therefore simply point to a resource on the classpath coming from a JAR and load that. It's simply enough to setup tests environments this way.
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("some-context.xml");
// boom you're ready to go
Note that Spring's JUnit support classes offer other (better) ways to setup testing environment.
But from that definition its not clear that
ClassPathXmlApplicationContext also implements
AbstractRefreshableApplicationContext and can be used to change beans
definition without stopping server.
That's what the javadoc is for.
FileSystemXmlApplicationContext is similar to the ClasspathXmlApplicationContext above, but it takes the configuration files from the file system instead of reading resources from the classpath.
ResourceAdapterApplicationContext states
org.springframework.context.ApplicationContext implementation for a
JCA ResourceAdapter. Needs to be initialized with the JCA
javax.resource.spi.BootstrapContext, passing it on to Spring-managed
beans that implement BootstrapContextAware.
I haven't worked with this one at all and I don't know where Resource Adapters are useful, but here are some more docs.
Just to add couple things to #Solitirios answer:
You forgot to mention several more context:
GenericApplicationContext
GenericXmlApplicationContext
AnnotationConfigApplicationContext
GenericWebApplicationContext
StaticWebApplicationContext
And many others.
In general, GenericApplicationContext is almost the same as StaticApplicationContext, the only difference between them in MessageSource support in StaticApplicationContext. Purpose for both of these classes is for small tests with tiny application context with couple beans.
GenericWebApplicationContext and StaticWebApplicationContext are also quite similar to each other, and typically they are used for emulation of Servlet container, e.g. tests or non-Servlet environment.
F.e. you can use something like this in your code (f.e. tests):
//create parent context
ApplicationContext xmlContext = new GenericXmlApplicationContext("classpath:/spring-*.xml");
//create mock servlet context
MockServletContext mockServletContext = new MockServletContext();
//create web context
GenericWebApplicationContext webContext = new GenericWebApplicationContext(mockServletContext);
//set attribute
mockServletContext.setAttribute(GenericWebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, webContext);
//set parent context
webContext.setParent(xmlContext);
//refresh context
webContext.refresh();
But there are couple contexts classes, which are worthy of attention. And considering your pre-requisites, I would choose one of them.
GenericXmlApplicationContext is very good alternative of ClassPathXmlApplicationContext and FileSystemXmlApplicationContext. Consider this example:
ApplicationContext context = new GenericXmlApplicationContext("classpath:some-context.xml");
is equivalent to
ApplicationContext context = new ClassPathXmlApplicationContext("some-context.xml");
or
ApplicationContext context = new GenericXmlApplicationContext("some-context.xml");
is equivalent to
ApplicationContext context = new FileSystemXmlApplicationContext("some-context.xml");
So GenericXmlApplicationContext looks more flexible.
AnnotationConfigApplicationContext is a context holder, if you don't want to keep your beans in XML-file.
//context creation
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
//context class
#Configuration
#ComponentScan("com.examples.services")
public class AppConfig {
#Bean
public DataSources dataSource() {
DataSource ds = new BasicDataSource();
//... init ds
return ds;
}
}
More information you can find here.

Spring does not find beans generated by annotations

I want to retrieve from my spring context all beans that are of a certain class (or subclass). But this only detects beans that are specifically defined by xml. Beans that are defined by annotations, such as #Serviceare not detected here. (Although inside the app they are detected, initialized, and autowired perfectly).
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext("*-context.xml");
Map<String, DataUpdater> beans = ctx.getBeansOfType(MyClass.class, true, true);
// why are beans missing?
I have seen similar problems and I never got getBeansOfType() to work correctly. My solution:
#Autowired
public void setMyClasses( List<MyClass> beans ) {
...
}
Spring will collect the list somehow and inject it. If you don't need to know when the list is injected, you can also inject it as a field:
#Autowired
private List<MyClass> beans;
You must search your beans also in
AnnotationConfigApplicationContext
If you want search in XmlContext and AnnotationContext you must combine them with
#ImportResource("classpath:xmlcontext.xml")
In annotated config
Or you can try implement ApplicationContextAware interface and search in Context provided by it.
Sorry, some stupid error... I was not properly loading my xml files, however beans were being instantiated as some background process was creating a parallel xml context with the correct files.

ApplicationContextInitializer in a non-web Spring Context?

I've created an ApplicationContextInitializer implementation to load properties from a custome source (ZooKeeper) and add them to the ApplicationContext's property sources list.
All the documentation I can find relates to Spring web-apps, but I want to use this in a standalone message-consuming application.
Is the right approach to instantiate my implementation, create the context, then pass the context to my implementation 'manually'? Or am I missing some automatic feature fo the framework that will apply my initializer to my context?
I have found it simple enough to implement the SpringMVC's strategy for Initializing a context by initializing with a blank context. In normal application contexts, there is nothing which uses an ApplicationContextInitializer, thus you must execute it on your own.
No problem, though since within a normal J2SE application given you have ownership of the context loader block, you will have access to every stage of the lifecycle.
// Create context, but dont initialize with configuration by calling
// the empty constructor. Instead, initialize it with the Context Initializer.
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
MyAppContextInitializer initializer = new MyAppContextInitializer();
initializer.initialize( ctx );
// Now register with your standard context
ctx.register( com.my.classpath.StackOverflowConfiguration.class );
ctx.refresh()
// Get Beans as normal (e.g. Spring Batch)
JobLauncher launcher = context.getBean(JobLauncher.class);
I hope this helps!
If I understand the problem correctly, you can find the solution in Spring documentation Section 4. The IoC container
An example on how to start your app is here - 4.2.2 Instantiating a container
Also have a look at 5.7 Application contexts and Resource paths
Not sure about other versions, but in Spring 4:
AbstractApplicationContext ctx = new AnnotationConfigApplicationContext(yourConfig.class);

Create Beans in Spring dynamiclly

I am using Spring3.1
My application will have kind of bean-manager.
That manager will be able to retrieve request and on each request I need to create new instance of bean dynamically which will be initiate with it's own unique params.
The params will be retrieved via the request method.
This bean must be alive and work asynchronously. (For example it will listen to jms calls, execute methods by demand and so on..)
Moreover I want to have the option to destroy beans also.
Those bean could be resemble as sessions so when the user log off i will destroy those beans.
I understand that I have to create some kind of bean-list or beans pool and manage it with some kind of manager.
How can I create those beans dynamically and have them remain them alive until I destroy them?
Any idea how could I implement such thing?
Well in this sense, the easiest way would be to create a StaticApplicationContext setting its parent context as the common context (the one holding the beans you want to share over all). This you could reach by doing something like:
StaticApplicationContext innerContext = new StaticApplicationContext(parentContext);
after this, you probably want to declare the bean you want to instantiate over Spring in order to attach all the AOP stuff, Autowiring and other functionalities, therefore you will need to do something like:
innerContext.registerSingleton("beanName", beanClass);
After registering you could instantiate the bean like:
innerContext.getBean(beanClass);
Of course there is the implementation of scope Session for spring and therefore I advise you to check the WebApplicationContext documentation, method loadParentContext that you basically pass the ServletContext as paramenter.
I've also found many trouble in creating a bean dynamically at run-time and used it anywhere in application..
Here is complete code
static ApplicationContext appContext = new ClassPathXmlApplicationContext(
new String[] { "Spring-Question.xml" });
static StaticApplicationContext innerContext = new StaticApplicationContext(appContext);
Create the bean and set the values e.g.
innerContext.registerSingleton("beanName", Test.class);
Test test = innerContext.getBean(Test.class);
test.setA(3);
test.setB(4);
Then Re-Use the bean anywhere in application....
Test test = innerContext.getBean(Test.class);
System.out.println(test.setB(4));

Categories