I'm building a J2EE application in which I want to allows plugins. I'm fairly convince of the goodness of IoC framework, and so the application will have one to manage services.
Now, I want to allows plugins to be added as simple JAR dropped in the classpath + perhaps a simple configuration file to edit to activate them, in no way something looking like Spring XML config files.
Most of the plugin architecture will be base around strategy/pipeline/chain of command patterns: for example the best plugin for an action is chosen by strategy, several plugins add filtering actions to an user input thanks to a pipeline, and so one.
So, I want to be able to:
define service interfaces in the core application,
set-up core implementation for extensible services with the chosen pattern in the main application,
let third party plugins register themselves in these hooks.
The first 2 points are quite easy, with or without IoC. The last one seems more complex without support at the IoC container level, or at least there is a lot of plumbing to do (how to manage classpath/sevice discovery, how to manage service orders in pipeline when the context change (new plugins), how to manage service overriding, etc).
I do know that Tapestry5 is great in that regards[1], but I can't find anything really relevant for Spring and Guice. And my company is more a String/Guice one than a T5 one (well, if I'm able to show that it's the best solution...)
So I'm wondering:
if I missed some obvious documentation;
if my requirement are so specials;
if an IoC container is not the right tool for that, and I should look for OSGi or something else.
Thanks for any tips !
[1] http://tapestry.apache.org/tapestry5.1/tapestry-ioc/configuration.html
I'm not sure how this would work with exactly what you're looking to do, but Guice's basic mechanic for handling plugins is Multibindings. How you handle discovery of plugins is up to you, but there are a variety of choices including scanning the classpath for implementations of plugin interfaces, having plugins provide a Module that adds their implementation(s) to the multibinder(s), using a config file that lists the plugin implementation classes, etc.
As the link mentions, you'd need OSGi if you need plugins to be addable at runtime with no restart.
Have you considered having a look at the Java EE 6 solution - CDI, implementation is named Weld based on JBoss Seam - which might be useful?
Once you start dropping in jars and their dependencies and then go though a couple of iterations of this with different plugins and different dependency versions, then you will start to feel the pain that many "application host containers" succumb to.
One possible solution to this problem is OSGi, although I did note a Tapestry blog highlighting the pitfalls of the OSGi approach:
http://blog.tapestry5.de/index.php/2010/01/19/tapestry-ioc-modularization-of-web-applications-without-osgi/
Related
When I first started looking at OSGi I was under the impression that you could just build a JAR and as-long as it had a manifest file, you could deploy it in a OSGi container. I imagined building my modules in a classic way (maven), and maybe use some plugin or something of the sort to write the manifest, I could then have my module that would basically be a standalone application communicating with other modules through OSGi.
Further reading about OSGi, I'm beginning to see more examples of it being used at a more low-level and basically replacing dependency injection and providing cross-cutting concern services like logging. And seems that using things like hibernate or others, is a problem... (or maybe I'm just missing something).
At least for me, I don't really see the point of having a such fine-gained level of modularity and integration to OSGi, I would much rather have a separate modules, each one of them having its own set of technologies and frameworks, and possibly a web resources and persistence layer. Is this achievable with OSGi? If yes, can you point me in the right direction, examples etc.?
edit, added some more details of how I'm trying to use OSGi:
I'm just envisioning the possibility of having a more than one-class module, that might have a more higher-level responsibility.
Like say agenda module. In this case I want to have things like, persistence of the events, add events, list events with filters, etc...
This agenda might have several internal classes, and might even need a persistence layer. So I would like to use something like Guice to DI those classes, and some JPA to persist my data.
I can understand that some X-cutting concerns like server or logging can have a bundle, but the data model is specific to the agenda bundle. So I think my question was at the end What is and what is not possible to do inside a bundle? And what should and shouldn't be done inside as a general practice?
Thanks!
Mauricio
You can use OSGi without forcing any dependencies on OSGi on the application code. However, since OSGi provides modularity, the middleware (your layers) need to have some knowledge of OSGi. The problem is that in a modular world you want to hide implementation details, that is the whole purpose. However, things like Spring and Hibernate tend to assume the classpath has no boundaries and they run head on into the fences. Fortunately, more and more middleware is becoming prepared for this, I heard Hibernate now has an effort and JPA is also available in OSGi.
OSGi is many things to many people, and you can almost pick and choose what parts of it you want to use:
Do you have a plain library that doesn't use any other dependencies? Sweet, just put up a minimal MANIFEST.MF listing the public packages, use maven to build your JAR and you're done.
Do you have dependencies? Same as (1), you just add the imported packages in your manifest.
Do you need to perform some initialization? Write an Activator, and mention it in your manifest.
Services? Just put the dependencies and descriptions of those in XML files and add them in the manifest.
And so on - just use the level where you are comfortable.
On the other hand, if you want to do web applications you really need to consider the architectural interplay between OSGi, the libraries you use, your application manager and the servlet/jee/whatever container. At what level will OSGi reside? In a general sense, there are OSGi->container->app, container->OSGi->app and container->app->OSGi solutions, and each has their own idiosyncrasies.
Concerning building with maven, you can use the Maven-Bundle-Plugin it helps you to build OSGi bundles without having to write the manifest on your own. All the required meta information will be in your POM.
Dependency injection can be achieved on top of the module layer. One possible solution would be Declarative Services which enables you to inject via an XML description or code annotations. It strongly reflects the dynamic nature of OSGi Services (dynamic binding unbinding of services).
The alternative is Blueprint which is based upon spring and features a very similar syntax. One key feature is that it can abstract the nature of binding and unbinding of services. If you think about using Spring, use Blueprint.
OSGi only implies how you structure your modules. You get a well defined graph of module interactions (who imports/exports a package? Who exports Services and who uses it?)
therefore you can build an enterprise architecture on top of it by building cohesive bundles for every task.
OSGi is sometimes referred to as a service-oriented architecture for the JVM. Looking at bundles as modular units that provide services helps define the right granularity: you'll usually have API bundles which are just here to provide java packages that define APIs, service bundles that provide implementations of these APIs, and utility/auxiliary bundles that provide the cross-cutting services that you mention.
You can use some dependency injection frameworks on top of OSGi, but from my experience (with Apache Sling and Adobe CQ5) keeping things simple is often better. The OSGi Service Component Runtime and Configuration Admin provide all I need to manage services, dependencies and configurations, especially if you design your system for that from the beginning.
You can find a bit more about our experience with OSGi in designing Adobe CQ5 in my "tales from the OSGi trenches" slides at http://www.slideshare.net/bdelacretaz/tales-from-the-osgi-trenches-2012-short-form-edition - that might help get a better feel for how OSGi is used in building complex systems.
I've searched on internet and here on SO, but couldn't wrap my mind around the various options.
What I need is a way to be able to introduce customer specific customization in any point of my app, in an "external" way, external as in "add drop-in jar and get the customized behavior".
I know that I should implement some sort of plugin system, but I really don't know where to start.
I've read some comment about spring, osgi, etc, can't figure out what is the best approach.
Currently, I have a really simple structure like this:
com.mycompany.module.client.jar // client side applet
com.mycompany.module.server.jar // server side services
I need a way of doing something like:
1) extend com.mycompany.module.client.MyClass as com.mycompany.module.client.MyCustomerClass
2) jar it separately from the "standard" jars: com.mycompany.customer.client.jar
3) drop in the jar
4) start the application, and have MyCustomerClass used everywhere the original MyClass was used.
Also, since the existing application is pretty big and based on a custom third-party framework, I can't introduce devastating changes.
Which is the best way of doing this?
Also, I need the solution to be doable with java 1.5, since the above mentioned third-party framework requires it.
Spring 3.1 is probably the easiest way to go about implementing this, as their dependency injection framework provides exactly what you need. With Spring 3.1's introduction of Bean Profiles, separating concerns can be even easier.
But integrating Spring into an existing project can be challenging, as there is some core architecture that must be created. If you are looking for a quick and non-invasive solution, using Spring containers programmatically may be an ideal approach.
Once you've initialized your Spring container in your startup code, you can explicitly access beans of a given interface by simply querying the container. Placing a single jar file with the necessary configuration classes on the classpath will essentially automatically include them.
Personalization depends on the application design strongly. You can search for a pluggable application on the Internet and read a good article (for an example: http://solitarygeek.com/java/a-simple-pluggable-java-application). In the pluggable application, you can add or remove a feature that a user decides. A way for the pluggable application is using the Interface for de-coupling of API layer and its implementation.
There is a good article in here
User personalisation is something which needs to be in the design. What you can change as an after thought if the main body of code cannot be changed, is likely to be very limited.
You need to start be identifying what can be changed on a per user basis. As it appears this cannot be changed, this is your main limiting factor. From this list determine what would be useful to change and implement this.
I'm writing a server application which makes use of external modules. I would like to make them to be upgradeable without requiring server restart. How do I do that? I've found OSGi but it looks very complicated and big for my task.
Simple *.jar files are ok, but once they are loaded, I suppose, I cannot unload them from VM and replace with another version on-the-fly.
What approach can you suggest?
It seems like OSGi is exactly what you're asking for. It can be complex, but there are ways to deal with that. Some of the complexity can be mitigated by using SpringDM or something similar to handle the boilerplate tasks of registering and consuming services in the runtime. Annotation-driven service registration and dependency injection really reduces the amount of code that needs to be written.
Another way to reduce complexity is to deploy the bulk of your application in a single bundle and only deploy the parts that need to be modular into their own bundles. This reduces your exposure to registering and using services from other bundles in the runtime as well as reducing the complexity of deployment. Code running within a bundle can use other code in the same bundle just as in a standard Java app - no need to interact with the OSGi runtime. The opposite of this approach is to break up your application into lots of discrete bundles that export well-defined services to other bundles in the system. While this is a very modular approach, it does come with extra complexity of managing all those bundles and more interaction with the OSGi runtime.
I would suggest taking a look at the book "OSGi in Action" to get a sense of the issues and to see some decent samples.
It would at least require you to define your custom classloader... I don't see how can this be simpler than just using Felix, Equinox, Knoplerfish or any open source Osgi runtime to do the task.
Maybe SpringDM is simpler...
What you're going for is definitely possible. I believe that you can unload classes from memory by loading them in a separate ClassLoader and then disposing that ClassLoader. If you're not wanting to go all out and use OSGI, I'd recommend something like JBoss Microcontainer (http://www.jboss.org/jbossmc) or ClassWorlds (http://classworlds.codehaus.org/). It's not too terribly difficult to write something like this from scratch if your needs are specialized enough.
Hope this helps,
Nate
If you follow the ClassLoader route (is not that difficult, really), I suggest each module to be packaged in its own jar, and use a different ClassLoader to read each jar. that way, unloading a module is the same as "discarding" the ClassLoader.
OSGi is not so complicated - using PAX runner with maven worked as a breeze.
Or implement your own ClassLoader and set it to JVM :
java -Djava.system.class.loader=com.test.YourClassLoader App.class
we are trying to develop a web application framework and build implementatins on top of it. This framwork will be versioned in SVN, live its own life in parallel to those implementations. It will have lots of spring config files, security config and so on. We would like to use those in those implementations.
What structure should such an project have? Keep everything together? Link particular folers (implementations) in "svn: externals"? We would like to use Maven, and create an archetype for those implementations, but is it possible to update the archetype after it has been changed in implementation applications?
Regards,
This is a good example :
http://www.sonatype.com/books/mvnex-book/reference/web.html
Also this book is very useful resource when starting with maven
I found this also :
http://www.avajava.com/tutorials/lessons/how-do-i-create-a-web-application-project-using-maven.html
I'd suggest you create your framework project as a simple jar project to include in your implementation, which would be war projects. For the Spring config files you have three options then:
Package them into your framework jar. This would make it hard for the implementations to customize it. I would not recommend it, unless your configuration is definitively fixed.
Use svn: externals. I have not much experience with that, but I think dependencies between svn repositories would be hard to manage.
Maintain these configuration files per implementation. So, an archetype would help to get started with an initial configuration. Then maintain these configuration files as your framework evolves. This is what we do most of the time. The good thing about Spring configuration is that it often rarely needs to be touched once you are confident with it.
Our software currently has many features. I've been asked to make a free trial version which consist of a lightweight version of the full software. Only a few specific features would be available in the trial. And since a jar file isn't encrypted, I was relunctant to release a full version with hardcoded restrictions. I want to be able to have 2 jars : 1 containing the basic features and 1 with the advanced features.
The features are in different menus. It would be nice it the code would try to load the jar with the extra features at start up and display a message (like : this feature is unvailable in the trial) when the non-paying user selects an advanced menu. On the other hand, a paying user with access to the advanced features jar wouldn't know the difference (I'm talking about the difference between now, 1 jar, and the new method, 2 separate jars).
Any tip on how to proceed ?
Any warning on common mistakes to avoid ?
Any better strategy than the separate jars ?
Edit : The best suggestion so far describes how to do my crippleware, but also warns me not to do a crippleware. So what do should I do ?
As you mentioned, you would probably have 2 jars:
1 with the basic features and stubs for the advanced features.
1 with the actual advanced features.
You could use a factory class with a config setting to determine whether to create the stub classes or the real classes - e.g. "FancyFeatureClass" or "FancyFeatureClassStub". "FancyFeatureClassStub" would be included in the "lite" distribution, but "FancyFeatureClass" would only be in the advanced features jar.
If they tried to change the config setting to create the real class without having the jar with the real classes, they would just end up getting class not found errors.
When upgrading, add advanced features jar to the classpath and change the config setting to tell the factory class to create the real classes instead of the stubs. Assuming your app could be split up that way, it should work fine.
As for common mistakes - I think you've already made one - probably not your fault though :)
"Crippleware" is a bad way to evaluate a product. Better to release a full featured version with an expiration or a nag screen than to release a crippled product. Not having those advanced features would probably make it difficult for someone to really evaluate the product.
Many technologies allow pluggable features (called plugins or addons usually).
The idea is that your core code (or framework) declares some interfaces (a well-thought API is ideal). Plugins can provide new implementations of an interface, and register it to the framework.
In its boot sequence, your framework will look (through some convention, in a file for example) if there are plugins, and give them a chance to execute their own boot sequence, consisting of the registration.
After the boot phase, a runtime example (for menus) : The framework looks it the registry where he stores the menus. The registry contains the menus the framework himself declared, plus any additionals provided by plugins... It displays all of them.
If you want specifically the behavior you asked for, I would implement this as follow :
menus available in all cases are declared and implemented in the framework
menus available only in the expanded edition are implemented twice :
in the framework, the implementation would simply display a message
(like : this feature is unvailable in the trial
in the plugin (= paid edition), it would override the previous implementation with the real one, that does the real job.
That way, you paying users have all normal functionality, with the trial version shows the warnings.
Many technologies exist to implement this, the best choice depends on what you already know/use/feel confortable with :
interface implementation is plain java, a string in the manifest of your plugin jar can mention the class to start.
Eclipse RCP has full implementation of menus that way (so you would have nothing to code, only configuration)
Spring is also pretty good when you use interfaces ...
Using a separate Jar which implements the paid for features (and a separate lite front end that displays a suitable message like 'not available' if it gets a ClassNotFoundException) would be the simplest way to do it.
There are many frameworks, up to and including Eclipse RCP for distributing UI applications in a modular form - but this will be overkill for your needs.
In fact, you don't even need two Jars, as long as your build process has the option to compile/package a sub-set of the Java classes in the Jar that you build as part of the distribution process. Just don't include the paid for features.