Getting Jar file after its OSGi related URI - osgi

In a specific point in my deployed OSGi bundle, I get a jar file URI in OSGi standard format, jar file that I need to parse for entity classes. So, having the URI like: bundle://233.0:1, would it be possible to get the jar file so that, I will be able to parse it for what kind of entity it has?
Note: I'm trying to solve an issue that I have with OpenJPA, Apache Servicemix and Spring Framework.
If you need any further clarifications, ask me please.

You do not need the jar. You can query the entries of a bundle with the following functions:
http://www.osgi.org/javadoc/r4v43/core/org/osgi/framework/Bundle.html#findEntries(java.lang.String,%20java.lang.String,%20boolean)
http://www.osgi.org/javadoc/r4v43/core/org/osgi/framework/wiring/BundleWiring.html#findEntries(java.lang.String,%20java.lang.String,%20int)
http://www.osgi.org/javadoc/r4v43/core/org/osgi/framework/wiring/BundleWiring.html#listResources(java.lang.String,%20java.lang.String,%20int)
First one returns only entries that is available in the bundle directly. Second one returns entries from the bundle and its fragments. Third one returns entries that the bundle's classloader sees (entries of the bundle, its fragments and entries from imported packages)

Related

Spring how to get Maven artifact name in runtime

I have a Spring Integration requirement , where I need to externalize the libraries and properties file from my war file. I am able to achieve this through Maven assembly plugin, where i create a zip file which may contain
lib/*.jar
properties/{artifactId}/*.properties
The reason I am adding the artifact Id to the path is, I will be creating 100s of wars in future and would need to distinguish between them.
This wars will not contain Web.xml and the Initializer is part of one of my libraries file.
THe Initializer should know the artifactId in order to load the correct properties.
With maven, the maven artifact details gets published to
META-INF/maven/${groupId}/${artifactId}/pom.properties
META-INF/maven/${groupId}/${artifactId}/pom.xml
If I could move these files to
META-INF/maven/pom.properties
META-INF/maven/pom.xml
My application would be able to read the artifact id from pom.properties.
I need help in achieve this.
Or if there are any other approach please help in solving the issue.
The Maven archiver component does that: see here at addMavenDescriptor element. It doesn't seem to be possible to customize the paths of these files.
But I guess every property you need can just be placed in a specific file and so you just have to create a resource file (properties like) containing all the information you want and let Maven filter that file for you.

How can I test if a jar is an OSGi jar?

Maybe it is a silly question, but what is the best way to test if a Java Archive (jar) file is an OSGi bundle? That is, what are the minimal requirements for the jar to be fully compatible? Is it the mere presence of a META-INF/MANIFEST.MF (I don't think so)? If not, what are the minimal fields that must be provided by this file?
Practically, how should I test if the jar is an OSGi jar?
Look for the Bundle-SymbolicName header in the MANIFEST.MF. This is the only mandatory header in an OSGi bundle, at least since Release 4.0 of the OSGi specification. Therefore if the Bundle-SymbolicName header is defined, then the JAR is an OSGi bundle. If not, then it is just a JAR.
A bundle is a group of Java classes and additional resources equipped with a detailed manifest MANIFEST.MF file on all its contents, as well as additional services needed to give the included group of Java classes more sophisticated behaviors, to the extent of deeming the entire aggregate a component.
The OSGi spec describes the bundle as a "unit of modularization" that "is comprised of Java classes and other resources which together can provide functions to end users.".
a bundle is a JAR file that:
Contains [...] resources
Contains a manifest file describing the contents of the JAR file and providing information about the bundle
Can contain optional documentation in the OSGI-OPT directory of the JAR file or one of its sub-directories
In short, a bundle = jar + OSGI information (specified in the JAR manifest file - META-INF/MANIFEST.MF), no extra files or predefined folder layout are required.
I guess the only qualification be required is that there are a bundle of classes and that it contains a MANIFEST.MF file which contains valid OSGi headers.
Consider this link
As well as this
Answering your question, the only way to test the bundle it to check if the MANIFEST.MF file exists and contains valid headers.

Camel xquery endpoint with OSGi bundle uri

I have an OSGi bundle (deployed into Karaf 2.2.4) that starts a Camel (2.10.0) context. The Camel context's routebuilder has some xquery endpoint URIs such as
"xquery:classpath:Dir1/Dir2/example.xq"
When the context tried to resolve that URI, it failed since the Camel bundle is not in the same classpath as where the .xq file resides. So, I created a url expand function that turns
"xquery:classpath:..."
into
"xquery:bundle://42.0:6/..."
since I had dealt with bundle URIs and the OsgiBundleResourcePatternResolver earlier in my project when dealing with a ClassPathScanningCandidateComponentProvider (Spring 3.1.1). Unfortunately, I can't seem to find a way to make Camel's XQueryComponent use my OsgiBundleResourcePatternResolver.
Am I going about this the right way? Is there an easier way to do this?
If I am, how can I make sure the XQueryComponent can understand a bundle: URI?
Also, is it possible for me to make sure any camel component can understand a bundle: URI?
You application that has the Camel route with the above xquery endpoint, would need to import the package where the xq file is located, eg the package that represents "Dir1.Dir2".
So in the META-INF/MANIFEST.MF which has the OSGi imports|exports. You should have an import for that given package.
And to answer your 3 bullets
No, see above
You would need to extend this component and add your own logic for the "bundle"
No, not really, as you would need to add logic to camel-core/camel-core-osgi.
Also the bundle id of an application can change, so its not advised to refer to a bundle by its id. And you cannot assign the bundle id, that is self assigned by the osgi container.
Thanks to Claus' answer, I was able to realize that my .xq file was not in the right directory in its .jar.
Dir1 resided in root of its .jar file. While running the application in a non-OSGi web container worked fine, Karaf appears to be more strict regarding where resources should be in my .war file. I moved the .xq files to WEB-INF/classes/Dir1/... and now am no longer receiving FileNotFoundExceptions when the code uses xquery:classpath:Dir1/Dir2/example.xq

cxf webservice in standalone spring application packaged as jar-with-dependencies using maven

When running the packaged app like "java -jar my-app-0.0.1-SNAPSHOT-jar-with-dependencies.jar", I get the following error:
org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 47 in
XML document from URL [jar:file:/.../cxf/javafirst/target/my-app-0.0.1-SNAPSHOT-jar-with-dependencies.jar!/application-context.xml]
is invalid; nested exception is org.xml.sax.SAXParseException; lineNumber: 47;
columnNumber: 61; cvc-complex-type.3.2.2: Attribute 'sendServerVersion'
is not allowed to appear in element 'httpj:engine'.
This is due to an outdated http-jetty.xsd schema published at apache.org. And that is NOT my problem. My problem is that this does not happen in cases like:
maven jetty:run
or
maven exec:java
where the service runs directly against the unpacked binary directories and obviously finds the updated and correct http-jetty.xsd schema file.
I want to do basically one thing:
put the webservice into one jar including dependencies. That should also include all XML schema files because, obviously, it is not a good idea to make a web service dependent on outside resources.
What's the best way to do that using maven?
My possibly naive solution would be to copy the XML schema files manually into the resources directory and tell CXF to resolve them in the jar file. Therefore I have two more specific questions:
1.) Is it possible to let maven find the XML schema files and copy them into appropriate places?
2.) What's the recommended way to make CXF look up the schema files in the jar file?
3.) Is there any better, best-practice solution to that problem?
My maven configuration regarding the maven assembly plugin is the direct combination of the last two sections at http://maven.apache.org/plugins/maven-assembly-plugin/usage.html.
Spring has a very good mechanism to resolve the schema files that it requires - it typically does not download it from the web at all, instead using locally available files within jar files to get the schema and validate the xml, for eg. consider the context custom namespace schema in Spring, if you look at the META-INF/spring.schemas file in spring-context.jar file, you will see an entry along these lines:
http\://www.springframework.org/schema/context/spring-context-3.1.xsd=org/springframework/context/config/spring-context-3.1.xsd
basically what it is saying is to resolve the spring-context-3.1.xsd files from the classpath org.springframework.context.config.spring-context-3.1.xsd file
This applies for any third party library also, which in your case is http-jetty.xsd.
I think what I would recommend is to simply create a spring.schemas file in your jar file in META-INF/ folder, put an entry for the full path to the schema and replace it with a classpath version of http-jetty.xsd.

hbase and osgi - can't find hbase-default.xml

as hbase is not available as osgi-ified bundle yet I managed to create the bundle with the maven felix plugin (hbase 0.92 and the corresponding hadoop-core 1.0.0), and both bundles are starting up in OSGi :)
also the hbase-default.xml is added to the resulting bundle. in the resulting osgi-jar, when I open it, the structure looks like this:
org/
META-INF
hbase-default.xml
This was achieved with <Include-Resource>#${pkgArtifactId}-${pkgVersion}.jar!/hbase-default.xml</Include-Resource>
The problem comes up when I actually want to connect to hbase. hbase-default.xml can not be found and thus I can not create any configuration file.
The hbase osgi bundle is used from within another osgi-bundle that should be used to get an hbase connection and query the database. This osgi-bundle is used by an RCP application.
My question is, where do I have to put my hbase-default.xml so that it will be found when the bundle is started? or why does it not realize that the file is existing?
Thank you for any hints.
-- edit
I found a decompiler so I could view the source where the loading of the configuration is executed (hadoop-core which does not provide any sources via maven) and I now see that the Threads contextClassLoader is used (and if not available the classLoader of the Configuration class itself), so it seems to me that it can't find the resource, but, it should, according to the description, also check the parents (but who is the parent in an OSGi environment?)?
I tested to get the resource from the OSGi-bundle that should use hbase, where I added hbase-default.xml to the created jar file (see above), and there I get a resource when I get the contextClassLoader of the thread. When I explored the code a bit more I realized that there is no way to set the classloader for the HBaseConfiguration (although it would be possible to set the classloader for a "simple" hadoop-Configuration, HBaseConfiguration inherits from, but the creation procedure of HBaseConfiguration does not allow it, as it simply creates a new object within the create() method.
I really hope you have some idea how to get this up and running :)
Thread.currentThread().setContextClassLoader(HBaseConfiguration.class.getClassLoader());
Make sure the HBaseConfiguration class loaded in your OSGI bundle.hbase will make use of the thread context classloader, in order to load resources (hbase-default.xml and hbase-site.xml). Setting the TCCL will allow you to load the defaults and override them later.
If hbase-default.xml is in the .jar file which is in the CLASSPATH, that file normally can be find by java program.
I have read the hbase mailing list.
check your pom.xml:
in 'process-resource' phase, hbase-default.xml's '###VERSION###' would be replaced with the actual version string. however, if this phase configuration is set to be 'target', not 'tasks', the replacement would not occur.
You could have a look at your pom.xml, ant correct the label to if so.
faced this issue, actually fixed it by putting hbase-site.xml in the bundle which I was calling hbase from, found advise here:
Using this component in OSGi: This component is fully functional in an OSGi environment however, it requires some actions from the user. Hadoop uses the thread context class loader in order to load resources. Usually, the thread context classloader will be the bundle class loader of the bundle that contains the routes. So, the default configuration files need to be visible from the bundle class loader. A typical way to deal with it is to keep a copy of core-default.xml in your bundle root. That file can be found in the hadoop-common.jar.

Resources