I\'m developing a desktop application in java using spring and hibernate. I want to package it as a executable jar but I\'m having problems loading the context configuration XML
Provided your jar is in classpath; you can import bean definitions from jars using import
<import resource="classpath:/path-to.xml"/>
Why not use ClasspathXmlApplicationContext and load them using the classpath relative path?
Try with an ClassPathXmlApplicationContext
It is a 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.
Here is how you might do it:
Create yourself a Test class with the following content in it:
package com.test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new
ClassPathXmlApplicationContext("/com/test/appConfig.xml");
Integer someIntBean = (Integer) context.getBean("testBean");
System.out.println(someIntBean.intValue()); // prints 100, as you will see later
}
}
Now create the beans application config file named appConfig.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="testBean" class="java.lang.Integer">
<constructor-arg type="int" value="100" />
</bean>
</beans>
You create these files in a package called com.test
, next to each other. Add classpath references to your spring jars or pack them together into your own single jar file wich should look like this:
test.jar --- com
| |--- test
| |--- appConfig.xml
| |--- Test.class
|
|-- META-INF
| |--- MANIFEST.MF
|
|-- org
| |--- springframework
| |--- ...
| |--- ...
|-- ....
In your manifest file you will have this (use with a trailing blank line):
Main-Class: com.test.Test
And that is it.
When your run your file (double click or java -jar test.jar
) you should see 100 printed on the screen. Here is what I get from executing it (notice the 100 I was talking about above - on the last row):
Feb 23, 2011 11:29:18 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@ca2dce:
display name [org.springframework.context.support.ClassPathXmlApplicationContext@ca2dce];
startup date [Wed Feb 23 23:29:18 PST 2011]; root of context hierarchy
Feb 23, 2011 11:29:18 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [com/test/appConfig.xml]
Feb 23, 2011 11:29:20 PM org.springframework.context.support.AbstractApplicationContext obtainFreshBeanFactory
INFO: Bean factory for application context [org.springframework.context.support.ClassPathXmlApplicationContext@ca2dce]:
org.springframework.beans.factory.support.DefaultListableBeanFactory@199f91c
Feb 23, 2011 11:29:20 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@199f91c:
defining beans [testBean]; root of factory hierarchy
100
P.S. You don't absolutely have to include the Spring jars content into your own jar. You can have them available on the classpath when you run your app. I placed them like that since you mentioned one jar. Basically this is what you need:
test.jar --- com
| |--- test
| |--- appConfig.xml
| |--- Test.class
|
|-- META-INF
|--- MANIFEST.MF
I suppose you want to run your application as java -jar myapp.jar
In this case, use class ClassPathXmlApplicationContext within your class with the method main
.
public static void main( String[] args ) {
String config[] = { "spring-beans.xml" };
ApplicationContext ctx = new ClassPathXmlApplicationContext(config);
DataSource ds = (DataSource) ctx.getBean("dataSource", DataSource.class);
}
It's a terrible idea to try to implement your own ApplicationContext. That's too much work and too much room for errors.