Spring OSGi classpath resource issue - osgi

I'm trying to deploy a spring based bundle in osgi (fuse esb).In spring context, I'm referring to a db4o file which is inside resources folder. As per my understanding, a maven project will make sure that any file available under resources folder will be available in project classpath. I've kept the file under resources/META-INF/spring/repo/test.db4o.
Here's the entry in spring context.
<bean id="objectContainer" class="org.springmodules.db4o.ObjectContainerFactoryBean">
<property name="databaseFile" value="classpath:META-INF/spring/repo/test.db4o" />
</bean>
Once I install and try to start the application, I'm getting the following exception.
java.io.FileNotFoundException: OSGi resource[classpath:META-INF/spring/repo/test.db4o|bnd.id=258|bnd.sym=taxonomydaoimplbundle] cannot be resolved to absolute file path because it does not reside in the file system: bundle://258.0:1/META-INF/spring/repo/test.db4o
I've tried different combinations, but OSGi doesn't seem to recognize this file. Any pointer will be appreciated.
-Thanks

I found the issue finally. ObjectContainerFactoryBean is relying on OSGiResourceBundle to load the resource as a file object. Though OSGiResourceBundle exposes a method called getFile(), it doesn't work as intended in an OSGi environment. It always expects a file protocol whereas the resource returned as an URI has a protocol "bundle".Hence, the exception is being thrown. The workaround is to use a inputstream or getUrl. Since I didn't have the source code of ObjectContainerFactoryBean, I had to extend this class to provide my own implementation which loads the file as an inputstream.

Related

Blueprint/Spring can't find 'classpath:path/to/file.ext' resource having moved project from Talend 6.5.1 to 7.1.1

In a Talend ESB (SE) project, I have a bean instantiated in the "Spring" configuration using a route resource.
In version 6.5.1 the following (used as a parameter) works fine.
<bean class="java.lang.String">
<constructor-arg>
<bean class="org.springframework.util.FileCopyUtils" factory-method="copyToByteArray" >
<constructor-arg value="classpath:query/sqlQuery.sql" type="java.io.InputStream" />
</bean>
</constructor-arg>
</bean>
but this doesn't for in my Talend 7.1.1 project. It seems to be unable to find the resource. I've looked in the created .kar file, and the resource is in the project .jar in the query folder.
[EDIT] It appears that Talend 7.1.1 encloses the "Spring" configuration in a <blueprint> element, which perhaps has change the way in which this functions.
I presume that something has changed in the way Talend packages the route, or in the way that the Spring xml is interpreted. Camel has no problem finding resources, for example from("sql:classpath:query/sqlQuery.sql"), but the "Spring" classpath search seems not to be able to find them.
I've tried substituting classpath*: for the straight classpath in the parameter as that had been suggested in some of the answers I'd seen to "resource not found" questions, but this didn't seem to be valid and was interpreted as a straight filename.
Am I doing something wrong with the classpath declaration? Is there another way of setting a spring/blueprint bean property with the contents of a resource file?
I've also tried explicitly declaring a ClassPathResource bean and it claims the resource does not exist when using the getInputStream() method, despite the fact I can see it if I open up the contained jar file.
Has the wrapping of the created feature in Maven terms (from Talend 7) had some impact on the classpath I need to use?

Is it webapp-root/META-INF or webapp-root/WEB-INF/classes/META-INF (Tomcat 7)

Unless I put META-INF in the root, context.xml along with the resources defined (queues, jdbc connection pool, etc) are not read correctly and Spring throws exceptions during start up.
Now I end up with two META-INF folders, I need one on the classpath (WEB-INF/classes/META-INF) due to persistence.xml.
Is is okay to have two META-INF's? I always configured resources in Spring's applicationContext so didn't notice before.
Thanks.
I guess it is all right. They both might have slightly different purposes.
webapp-root/META-INF is directory for metadata of the web application, which you can access via servletContext.getResource("/META-INF/foo").
webapp-root/WEB-INF/classes/META-INF is directory for metadata of java classes, which you can read via getContextClassLoader().getResource("/META-INF/foo").

Accessing properties file from another module context

I use maven. My web application contains two modules and each has it's own spring context. First is packed to jar, the second one to war. The second one uses first module's jar and calls it's methods.
I need to add property file, which will be used by first module (via spring context). The main issue is that I should be able to access/edit this property file after war deployment.
How can I provide such a property file, that will be used in first jar module and can be changed after war module deployment?
Thanks.
Sorry, don't see the problem, you need to describe that better. From what I understood this is the way to go:
place a.properties in src/main/resources in the JAR module
use a PropertyPlaceholderConfigurer to make the properties available in the Spring context
it'll be packed in root of the JAR
the JAR ends up in WEB-INF/lib of the WAR which again is "root of the classpath" so to speak
Update, 2013-06-09
(question was updated based on comments to initial answer above)
Essentially what you seem to be looking for (still not quite sure) is how to load properties from a properties file that is not packaged with your WAR/JAR.
In this case you can skip all of the above steps except 2.
Use a PropertyPlaceholderConfigurer and specify the location of the file as classpath*:a.properties (see below)
Place a.properties anywhere on the classpath outside the WAR file.
Warning! Of course you can now edit the properties independently from releasing the WAR file but since Spring initializes the beans on application start and since all beans are singletons by default changes to the properties file won't become effective until you restart the app.
XML example
<bean class="....PropertyPlaceholderConfigurer">
<property name="location" value="classpath*:a.properties" />

Normalizing Spring Resource for use with JUnit & war?

I'm probably thinking about this incorrectly, but here's what I'm up against:
I'm injecting Spring Resource objects into my app that give me the location of security certificates, for example:<property name="certificateResource" value="SomeCert.p12" /> where certificateResource is of type org.springframework.core.io.Resource
Running under JUnit the Resource is a classpath resource and everything is fine. When deployed as a war under Tomcat the the Resource is in a Servlet Context and requires WEB-INF/classes/ prepended to the certificate.
I've tried a number of Resource prefix and wildcard combinations but can't come-up with a single string that satisfies both contexts. So far the "solution" is to override the bean definition in src/test/resources/test-applicationContext.xml but that means maintaining the strings in two locations.
Any pointers to better solutions would be appreciated, thanks.
I have tried to make a small but descriptive application using spring-test and spring-webmvc and using resources referenced in xml configs while these xml's are reused by production and testing spring configurations. Here is what I recieved: github.com/isopov/spring-resource-test
The central is the referencing of the prodcution xml config from the testing config:
<import resource="file:src/main/webapp/WEB-INF/applicationContext.xml" />
it is also possible to not import one xml from the other, but give each test several configs:
#ContextConfiguration(locations = { "classpath:test-applicationContext.xml",
"file:src/main/webapp/WEB-INF/applicationContext.xml" })
the resource itself resides in src/main/resources (I assumed you are using Maven or something derived from the "Standard Directory Layout") so is always accessible with "classpath:hello.txt" from any spring config.
I tested this with maven build, as web-application and running UTs inside Eclipse.

How can I package an extensible default Spring configuration in my framework?

It is the second time that I stumble across that issue and I haven't found a good solution yet. My problem is that I want to package a framework like JAR with a default Spring context and give the user of my JAR package the possibility to use this configuration (or even an ApplicationContext implementation) to add his own bean definitions (from another config file) and to use or overwrite definitions from the default context. Does anybody know a good way to do this?
The people using your jar will have to import your .xml file in theirs, with something like this:
<import resource="classpath*:/META-INF/spring-yourframework-init.xml" />
(/META-INF/spring-yourframework-init.xml is the path of your xml in your jar. This xml file is a regular spring configuration file)

Resources