Create Spring ApplicationContext from in memory XML - java

Is there a way to create an ApplicationContext (or whatever else in Spring you can use to do getBean("beanName") ) by passing in an XML file that is in memory? The only methods I've been able to find involve providing a file or directory.

You could give it a try:
import org.springframework.context.support.GenericXmlApplicationContext;
String xmlDef = "...";
ApplicationContext ctx = new GenericXmlApplicationContext(new InputStreamResource(new ByteArrayInputStream(xmlDef.getBytes("UTF-8"))))

Related

cannot find file with ClassPathXmlApplicationContext

I have a default package called com.voja.springtest and another one called com.voja.springtest.beans where I have an beans.xml file.
I can get it like so using FileSystemXmlApplicationContext :
ApplicationContext context = new FileSystemXmlApplicationContext("C:/Users/Voja/Desktop/_/vj/springtest/src/main/java/com/voja/springtest/beans/beans.xml");
But ClassPathXmlApplicationContext can't find it like so (and it should per the tutorial I am doing):
ApplicationContext context = new ClassPathXmlApplicationContext("com/voja/springtest/beans/beans.xml");
Why?
you use wrong parh , in your case it should be like :
ApplicationContext context = new ClassPathXmlApplicationContext("classpath*:beans.xml");
4.7.2.2 The classpath*: prefix
When constructing an XML-based application context, a location string
may use the special classpath*: prefix:
ApplicationContext ctx =
new ClassPathXmlApplicationContext("classpath*:conf/appContext.xml"); This
special prefix specifies that all classpath resources that match the
given name must be obtained (internally, this essentially happens via
a ClassLoader.getResources(...) call), and then merged to form the
final application context definition.
The Classpath*: portability classpath*: prefix
FileSystemXmlApplicationContext picks the XML file from absolute path by appending keyword "file" and also can fetch from classpath by appending keyword "classpath".
You can access the file as below
ApplicationContext context = new FileSystemXmlApplicationContext("classpath:spring-app.xml");

How to instantiate a class using Spring context.xml

I'm really not sure where to start with this because I am extremely new at Spring.
Currently I am instantiating a class like normal,
ClassImpl newImpl = new ClassImpl();
I want to do this through Spring's context.xml - so I've loaded the class as a bean-
<bean id="ClassId" class="ClassImpl"></bean>
How do I know instantiate ClassImpl by taking advantage of the fact that I have passed it in as a bean? That is, how do I give newImpl a new ClassImpl by making Spring inject it in?
You'd do something like:
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:" + [package_name/context.xml]);
ClassImpl newImpl = (ClassImpl) ctx.getBean("ClassId")
If you're loading it from a context.xml outside your project, I believe you can do
ApplicationContext ctx = new FileSystemXmlApplicationContext(path_to_context.xml);
ClassImpl newImpl = (ClassImpl) ctx.getBean("ClassId")

How to load this file path from inside a spring application

I was previously hard coding a path to load a json file like so:
JsonParser parser = jf.createJsonParser(new File("/some/path/here/myapp/WEB-INF/settings.json"));
So I tried to extract it out to a properties file like so, files.properties:
path.to.json=/some/path/here/myapp/WEB-INF/settings.json
Now how can I modify my call to jf.createJsonParser to load the file using the path from the files.properties path.to/json key?
I'm a little confused. Your title indicates that you are looking for a Spring solution, but you are not using IOC here, from what I can tell. Otherwise, you would be injecting the JsonParser bean and not instantiating it within your code.
Without seeing the global structure of what you are doing, I would do the following (assuming that you have Spring properly configured).
applicationContext.xml:
<bean id="jsonParser" factory-bean="<jf bean definition>" factory-method="createJsonParer">
<constructor-arg>classpath:/settings.json</constructor-arg>
</bean>
Then within your actual class that uses the JsonParser, have it autowired for simplicity sake:
class myClass{
#Autowired
JsonParser jsonParser;
public void myMethod(){
String data = jsonParser.doSomthingNeatHere()....
}
}
I've assumed that JsonParser is of scope prototype, but you can change it to singleton if that matches your needs more appropriately. As well, I've only given you a little pseudo-code to give you the idea of how to allow Spring to manage the life-cycle of the bean as opposed to you instantiating it yourself.
You can read more about Spring 3 and IOC here if you need additional reference.
If you can put your file into a source folder, do it and try "classpath:/"
Example:
new File( "classpath:/context/settings.json" );
I don't know whether your looking for a Spring specific solution, but I see nothing wrong with using the JCL.
Properties props = new Properties();
props.load(new FileReader(propsFile));
String jsonFile = props.getProperty("path.to.json");
JsonParser parser = jf.createJsonParser(new File(jsonFile));

Properties framework in java apps

I have been using spring for a while as my IOC. It has also a very nice way of injecting properties in your beans.
Now I am participating in a new project where the IOC is Guice. I dont understand fully the concept how should I inject properties in to my beans using Guice.
The question : Is it actually possible to inject raw properties ( strings , ints ) into my guice beans. If the answer is no , than maybe you know some nice Properties Framework for java.
Because right now I wanted to use the ResourceBundle class for simple properties management in my app. But after using spring for a while this just dont seem seriously enought for me.
this SO post discusses the use of various configuration frameworks, also the use of properties. I'm not sure it's to the point exactly for your needs, but perhaps you can find something of value there.
Spring provides for injection of configuration information found in XML files. I don't want the people installing my software to have to edit XML files, so for the kind of configuration information more properly in a plain text file (such as path information), I've gone back to using java.util.Properties since it's easy to use and fits into Spring pretty well, if you use a ClassPathResource, which permits path-free location of the file itself (it just has to be in the classpath; I put mine at the root of WEB-INF/classes.
Here's a quick method that returns a populated Properties object:
/**
* Load the Properties based on the property file specified
* by <tt>filename</tt>, which must exist on the classpath
* (e.g., "myapp-config.properties").
*/
public Properties loadPropertiesFromClassPath( String filename )
throws IOException
{
Properties properties = new Properties();
if ( filename != null ) {
Resource rsrc = new ClassPathResource(filename);
log.info("loading properties from filename " + rsrc.getFilename() );
InputStream in = rsrc.getInputStream();
log.info( properties.size() + " properties prior to load" );
properties.load(in);
log.info( properties.size() + " properties after load" );
}
return properties;
}
The file itself uses the normal "name=value" plaintext format, but if you want to use Properties' XML format just change properties.load(InputStream) to properties.loadFromXML(InputStream).
Hope that's of some help.
Injecting properties in Guice is easy. After reading in some properties from a file or however, you bind them using Names.bindProperties(Binder,Properties). You can then inject them using, for example, #Named("some.port") int port.

Getting FileNotFoundException in Spring

I want to create bean using BeanFactory, but I am getting an exeception: java.io.FileNotFoundException: \\WEB-INF\businesscaliber-servlet.xml.
Resource res = new FileSystemResource("//WEB-INF//businesscaliber-servlet.xml");
BeanFactory factory = new XmlBeanFactory(res);
if (factory != null && beanId != null) {
obj = factory.getBean(beanId);
}
he its working using this
ApplicationContext ctx = new FileSystemXmlApplicationContext("classpath*:/WEB-INF/businesscaliber-servlet.xml");
I believe you need to specify an absolute path and not a Web application relative path to FileSystemResource.
Try using ServletContextResource instead.
Resource implementation for
ServletContext resources,
interpreting relative paths within the
web application root directory.
The only issue is you need the ServletContext so:
ServletContext servletContext = ...
Resource res = new ServletContextResource(servletContext,
"/WEB-INF/businesscaliber-servlet.xml");
BeanFactory factory = new XmlBeanFactory(res);
if (factory != null && beanId != null) {
obj = factory.getBean(beanId);
}
It's worth noting that ideally you would retrieve this from an ApplicationContext. From 4.4 Resource Loader of the Spring Reference:
Resource template = ctx.getResource("some/resource/path/myTemplate.txt);
What would be returned would be a
ClassPathResource; if the same
method was executed against a
FileSystemXmlApplicationContext
instance, you'd get back a
FileSystemResource. For a
WebApplicationContext, you'd get
back a ServletContextResource, and
so on.
As such, you can load resources in a
fashion appropriate to the particular
application context.
So this is the preferred method of retrieving resources.
Alternatively since /WEB-INF/ is technically in the classpath you can use the classpath: prefix (as per your comment) or use ClassPathXmlApplicationContext (which will automatically return classpath resources).
Also theres no need to put double forward slashes in. Not sure why you're doing this. Perhaps a holdover from double backslashes, which are necessary?

Categories