We are considering to use Configuration Admin Service as a primary API for configuring components in our OSGi-based application. It would be nice if we could reuse some existing implementation so I'm trying to investigate and evaluate the most popular ones. I know there is:
Apache Felix Config Admin (org.apache.felix.cm)
Equinox Config Admin (org.eclipse.equinox.cm)
Are there any other implementations to be considered?
Also I was not able to find any good documentation for these implementations. I would be mainly interested in the implementation-specific details. For example I was wondering how different implementations persist the configuration data (e.g. multiple property files? XML file? multiple XML files? database?, ...).
Felix's Configuration Admin has a default implementation that persists to the file system, but they define a service interface (org.apache.felix.cm.PersistenceManager) for alternative backends that you could plug in instead.
The default implementation does the following:
The FilePersistenceManager class stores configuration data in
properties-like files inside a given directory. All configuration files are
located in the same directory.
Configuration files are created in the configuration directory by appending
the extension ".config" to the PID of the configuration. The PID
is converted into a relative path name by replacing enclosed dots to slashes.
Non-symbolic-name characters in the PID are encoded with their
Unicode character code in hexadecimal.
The three public implementations I know of are
Apache Felix
Equinox …source (this has moved recently)
Knopflerfish …front page and …source
Equinox's implementation of the ConfigurationAdmin service appears not to support fine control over the persistence policy, as Felix's does, and the Knopflerfish implementation looks (I've only read the source briefly) similar to Equinox's.
The Felix one appears to be the most recently updated and the most reliable.
At present these are the only ones I can find; at dm Server we made the decision to use Felix's bundle, and this is now obtainable from the SpringSource Enterprise Bundle Repository, where you can quick-search for Apache Felix or ConfigAdmin.
Just to complete the answer further: I personally also prefer the Felix implementation. For an example of how to change the way storage occurs at the back-end using a PersistenceManager, see also this implementation that uses standard Java property files as backing storage. Has some limitations, but at least allows you to store your configuration with your application and apart from your OSGi framework implementation.
Related
I'm writing a jee app deployed as a WAR to a container.
This app depends (maven dep) on a java lib packaged as a JAR.
The lib contains a client used by the jee app to talk to a backend.
The lib accepts the base uri of the backend (host+port+context-path) as a configuration.
What is the best way to configure the lib from the jee app so that one can provide configuration for multiple environments (e.g. backend production URI is different from test URI)?
I read about #Alternative annotation and ContextParam, but both seem jee specific AKA not understood by plain java...
Maven Assembly does not seem the way to go as it would imply having to deploy to our maven repo one artifact per environment.
UPDATE 1
What if the jee app contains one properties file per environment (dev, test, prod) and can pass the properties down to the lib via plain old java constructor?
I'll try and provide some answers / ideas to the topic. I would follow this approach:
Provide a fallback configuration file in the library.
Implement a default behavior in the library that looks for a predefined configuration file on the classpath which has higher precedence than the fallback (e.g. via java.lang.Class.getResourceAsStream(String))
Let the library provide a Java-API to read the configuration from a different location / ressource.
Let the library provide a Java-API to change specific configuration settings directly from client code.
You could also provide the possibility to configure your library via system environment variables and / or command line parameters.
This way, clients of the library can decide where the configuration resides, dependent on their technical landscape.
In JEE you could then use a ContextParam to set the location of the configuration resource, or to set specific configuration properties, or just provide a configuration resource in the standard location on the classpath.
If you use Spring or similar frameworks, you have loads of other possibilities to provide configuration to an application. Spring Boot provides some nice behavior out-of-the-box regarding this.
Underlying idea is that you have to provide means to the operator of the application to influence the configuration. Then it is possible to adapt configuration according to whether it is run on a developer's machine, in unit / integration testing conditions, in a staging environment or in production.
I would like to take several lists of Maven dependencies from the user, resolve and load each of them as contained applications. Here are the steps:
collect a list of all Maven dependencies (DONE)
resolve all dependencies with Aether (DONE)
resolve classpath with Aether (DONE)
bundle the above in a separate "container" (so that different Maven dependencies with potential conflicting version can be used).
repeat with other lists.
To give some context: I want to use the above in the context of UIMA, to be able to run different (natural language processing) pipelines that rely on different sets of libraries with different versions. My goal is to create an annotation-server in which one defines (Maven) dependencies and pipelines that can be called in a RESTful way. The pipelines (and their corresponding dependencies) should each run in a contained classpath environment (so as to avoid classpath clashes).
Is OSGi the way to go? Based on a classpath (:= a list of resolved jar), can I then build an OSGi bundle and deploy it? All programmatically? I do not have control over the maven dependencies (they are UIMA components, that's it), so no way to add OSGi metadata there.
Would maven-assembly-plugin combined with maven profiles take care of this for you?
You can filter dependencies differently on a per profile basis. You can use profile specific assembly descriptor documents and generate custom manifest to be placed in the war. You are describing a J2EE Web Application (war) assembly -- they will run in a firewalled classloader inside a servlet container so you generate a bunch of them based on the same source (just vary the web app context and the contents of the WEB-INF/lib on a per profile basis.
Drop them into the same Tomcat server, for example, and you are ready to go. Was this what you meant?
HTH,
Nick
You can certainly create a bundle that contains a list of jars, put all of those on the bundle's own classpath and deploy that bundle into an OSGi container. You probably do need to create a BundleActivator (which is the entry point for that bundle, like the main method is for traditional Java).
You then say you have multiple of such bundles, and do I understand correctly that you want to deploy each bundle in a separate container? If so, you can either use some kind of REST library to provide a REST endpoint for each bundle, or you can use OSGi remote services to publish a service that can be discovered by other containers.
I am not sure if this is what you mean, so I am also not sure if OSGi is the right way to go. From your description you use neither services (a very important reason to use OSGi as that decouples parts of your application from each other) nor do you intend to create different bundles for the components (another important reason to use OSGi). You are almost describing an architectural style currently hyped as "micro services". Can you please elaborate a bit more?
Based on your use case I'd suggest you look into the Java ServiceLoader API. The ServiceLoader API allows you to define an interface, and load implementations of that interface from different self-contained JARs. You can build your different libraries into their own jars, exposing the methods you need via the interface, and load them from your Java program independently. The ServiceLoader will even list the different implementations available for you.
From the documentation:
Suppose we have a service type com.example.CodecSet which is intended to represent sets of encoder/decoder pairs for some protocol. In this case it is an abstract class with two abstract methods:
public abstract Encoder getEncoder(String encodingName);
public abstract Decoder getDecoder(String encodingName);
Each method returns an appropriate object or null if the provider does not support the given encoding. Typical providers support more than one encoding.
If com.example.impl.StandardCodecs is an implementation of the CodecSet service then its jar file also contains a file named
META-INF/services/com.example.CodecSet
This file contains the single line:
com.example.impl.StandardCodecs # Standard codecs
The CodecSet class creates and saves a single service instance at initialization:
private static ServiceLoader<CodecSet> codecSetLoader
= ServiceLoader.load(CodecSet.class);
To locate an encoder for a given encoding name it defines a static factory method which iterates through the known and available providers, returning only when it has located a suitable encoder or has run out of providers.
public static Encoder getEncoder(String encodingName) {
for (CodecSet cp : codecSetLoader) {
Encoder enc = cp.getEncoder(encodingName);
if (enc != null)
return enc;
}
return null;
}
A getDecoder method is defined similarly.
That sounds a lot like you could use Apache Stanbol. It's a framework focused on semantic enhancement of content but can be used for any web based work flows involving content. You can define pipelines to process and/or store your data. There are components for NLP using Apache Tika and OpenNLP. As far as I know you can also integrate UIMA. It uses RESTful services and is based on OSGI.
If Stanbol doesn't fit your use case and you need to roll your own application, I think OSGI is still the way to go.
Depending on your use case you can either deploy bundles to a container or simply embed the OSGI framework in a small launcher app that loads the bundles you create.
Many Maven artifacts already contain OSGI metadata. Most of the time you can copy them to your bundle directory using the maven-dependency-plugin and load them directly as OSGI bundles.
Non-OSGI dependencies can be embed in your the bundles that need them. It should also be possible to setup a few maven plugins to modify the manifest to add some meta data based on the maven artifact ids and version and repack the dependencies as bundles (this won't work all the time though, since the Maven pom version and the packages' versions aren't always the same).
The users code and any required dependencies can be bundled up using the maven-bundle-plugin. It can generate the manifest for you.
For REST interfaces I usually would recommend JAX-RS (Jersey or Apache CXF DOSGI) but I haven't used the programmatic approach with those frameworks yet.
Do some implemented OSGi frameworks allow me to bundle css styles and javascript as well?
Or i have to use other approaches to do this?
One way is to create a WAB (Web Application Bundle), it's a war with OSGi manifest which needs a Web-ContextPath attribute, this doesn't necessarily be a war it may also be a jar with a war like structure.
Might want to take a look at the Pax Web Framework (or Karaf wich uses it).
The Pax Web framework provides all that is needed to deploy Servlets/JSPs resources etc. also in a OSGi manner. Yes also as Services via a Whiteboard approach. Another point is Servlet 3 and CDI, all of this is also supported by Pax Web (for CDI you'll also need Pax CDI)
Best take a look at the various samples and the integration tests.
You can have any resource in a jar. This is not the question of OSGi framework, but the question of the technology you would like to use. How will it find the resource in your jar.
E.g.: If you create a WAB, that behaves similar to a WAR.
Although WABs can be used with several OSGi based web server, I personally do not like them as they are monoholitic. There are alternatives to provide resources:
https://github.com/bndtools/aQute/tree/master/aQute.webserver
An implementation by Peter Kriens that allows us to download any files that are placed into the /static/ folder of any bundle. The Servlet is registered on the /static/ path so if you have a file in your bundle at /static/css/mystyle.css, you can access it via http://foo.com/static/css/mystyle.css
https://github.com/everit-org/webresource
Similar solution but this is based on bundle capabilities. The first release is expected in the end of October 2014, but the important logic is already implemented. This library needs OSGi 6.0 and Java 8 since the latest commit that might be a limitation for a while.
JSPs are other question. If you use a WAB and an embedded Servlet container with JSP support, they should work. You can also register the JSP servlet manually into your OSGi container based on the technology you use (e.g.: with whiteboard pattern).
Amdatu has support for this in the Web Resources component. You simply add your static resources to the bundle using the -Include-Resource bnd header and add a few manifest headers to serve the files directly.
An example of this could be the following. This example can be found in the Amdatu Chat example.
Include-Resource: \
app=dist/app
X-Web-Resource-Default-Page: index.html
X-Web-Resource-Version: 1.1
X-Web-Resource: /chat;app
I must have a really bad day cause no matter what I search for I only get to this link which has only the listing for the allowed XML tags for those deployment descriptors.
I'm pretty sure I saw once a document with a thorough description of those files, but I can't seem to find it right now.
:) GF Application Deployment Guide -> Elements of the Enterprise Server Deployment Descriptors
sun-ejb-jar.xml is an old naming convention for what is today called glassfish-ejb-jar.xml. It is still supported for backward compatibility (see the GlassFish 4 deployment guide, page B-2).
glassfish-ejb-jar.xml is a GlassFish specific deployment descriptor file, documented in the deployment guide. The deployment guide describes its technical structure and is a good start for any question you might have about a specific element of the file. Examples of how-to really use the file is spread out through the entire document base.
All other application servers will most likely ignore this file. Making your application dependent on the contents of this file is the same as making your application non-portable. Thus, it should be avoided as much as possible.
Let me quote the GlassFish deployment guide (page 1-3):
Unless otherwise stated, settings in the GlassFish Server deployment
descriptors override corresponding settings in the Java EE standard
descriptors and in the GlassFish Server configuration.
The overridable standard and portable descriptor file is ejb-jar.xml and is described in the EJB 3.2 specification. The presence of the file is optional and should probably not be used if all you do with the file is describe bean behavior and services from the application server that is used. Unless application developer and application deployer is different persons with different needs, or unless you have a requirement to define different beans based on the same class, then you'll be more than covered using annotations only. That way, declared application server services is more tightly bounded to the code that actually uses the services. It will increase the readability of your code and make more sense to more people. One arguable important and encouraged use of the file is to put customizable environment entries in the descriptor file. If your application is packaged in an EAR file, consider using the application.xml descriptor file for declaration of environment entries instead.
I have a java EE application EE5 EJB3. I develop using NetBeans 6.7 and GlassFish 2.x
I need to have a configuration file (*.xsl, *.xml) that is deployment/client specific.
My questions are:
1) where do I put files that are external to the ear file?
2) How do I load the files into a session bean? can I use injection?
I manage to inject a #Resource for the file name using the ejb-jar.xml.
Many thanks in advance.
G.
I guess this is not what you are expecting but the right answer is that you shouldn't do it! According to the EJB specifications and more precisely the Programming Restrictions:
An enterprise bean must not use the java.io package to attempt to access files and directories in the file system.
And this statement is followed by this explanation:
The file system APIs are not well-suited for business components to access data. Business components should use a resource manager API, such as JDBC, to store data.
The reasons behind this statement are:
Accessing the file system isn't transactional and would compromise component distributability.
Accessing the file system from an EJB would compromise its deployability (the resource isn't under the EJB container's control and the EJB can't be moved easily in a cluster).
Accessing the file system is a potential security hole.
Now that you know this, if you still want to do what you had in mind and if your EJB container doesn't restrict using classes from the java.io package, then I would put a read-only file on the classpath, preferably in a JAR, and access it using the getResource() or getResourceAsStream() methods of java.lang.Class. But really, you should keep the specification in mind, it's there to help you build portable applications.
If you can assemble one EAR per target deployment (maybe maven profile can help in this area), then you can then load it like a resource.
Another option would be to have a look at J2EE Application Deployment Specification (JSR-88) to have one EAR with N deployment plan per environment.
You can also decide to store the file on the filesystem (even though it's prohibited). If you want the path to be in the ejb.xml then you need again to assemble or deploy the EAR in different ways - no big gain then. Another option would then to use a Glassfish Custom JNDI Resource to have the possibility to configure the path right from the admin console. The your app. can load the file according to the path that is configured.
See this question: Process files in Java EE.
The specification forbids file access using java.io, it does not forbid file access in general.
One of the main reasons that files cause problems in enterprise applications is that they are hard to use safely and efficiently in a multi-user environment. In particular, file locks can heavily constrain scalability.
Using a class loader to read a configuration file once per session as suggested by Pascal is unlikely to cause problems on most application servers, except possibly in the case of hot deployment.
JNDI properties can be used as an alternative to a configuration file. JNDI properties are defined in the deployment descriptor and bind a value to a JNDI name at deployment time. The application can look up the value from inside the application using the JNDI name.