I am curious about an elusive - but potentially very powerful - DropWizard feature called Bundles. According to the docs:
A Dropwizard bundle is a reusable group of functionality, used to define blocks of an application’s behavior.
Given that DropWizard (DW) is extremely well documented, I’m shocked that this is really the only explanation on bundles. I see a few examples of them in the wild:
Asset Bundle
Cassandra Bundle
But what I don’t understand is: bundles seem to just be code packaged and distributed in JARs. So why can’t I just write “raw” (non-“bundle”-compliant) Java classes to do what I need, slap them in a JAR, then include that JAR on my build/compile classpath, ad then use them in my DW app? Of what use is a DW bundle, and when should one use them?
Bundles are like addons to Dropwizard that make it very easy to add small pieces of functionality. For example, if you use the assets bundle, you can attach a UI to your API for testing purposes and it will run on the same port and is very easy to use. Another example would be the Migrations Bundle that easily ties Liquibase into Dropwizard so you can run database migrations with the same jar. This also works well since your API could be accessing some sql database which has connection parameters defined in a yml file, the migrations would be able to run on the same database.
Let say you work for your Platform Team in your company, and your developers use Kafka as message-bus.
Then, you can ask the dev team to add the below configuration in their DW app, and you can write the bundle to parse the broker-uris, and build the Producer Instance.
With Integration with any Dependency Injection frameworks, all your have to do is #InJect the Producer Instance when you need.
kafka-broker-uris: <your kafka broker urls>
We can do the same thing using a library, and call a method that gets an broker-uri and return a producer object..
But, I believe, the main benefit comes from the Bundle knowing how to parse the configuration, and pre-builds necessary objects during the Initialize phase of DW lifecycle.
Also, if you want to set a standard in your company on how the config file has to be defined, then it is good to go with a bundle.
DW bundles are similar to "raw" JAR in the manner that both can be used to provide reusable functionality. However, the difference lies in the additional support that DW bundles enjoy. Bundles can be made configurable i.e. they can use the DW configuration file for configuration parameters
Related
I am currently working to add OSGi modularity to a project for the purpose of plugins. The basic idea is that users can develop their own plugins that can be added at runtime to the main application to extend or modify its functions and/or capabilities.
For example, the main application uses Restlets to define an HTTP API for the application. The user may wish to create a plugin to add an endpoint with a specific function. Or they may wish to create a new entity that is stored in the database with a specific purpose.
I understand that this is not a 'true' OSGi modular application implementation and after some research I managed to quite easily add OSGi capability to the existing project with embedded Felix. Along with felix.fileinstall the application watches a deploy folder and automatically installs and starts the jar bundles that are dropped into the deploy folder (stops and uninstalls when removed).
So the basic idea is implemented and work great. What I'm struggling to understand is how I define and publish the main applications API (that can be implemented by any plugin bundles). On the flip side I don't understand how bundle developers can gain access to that API info?
In order for a bundle developer to be able to utilise the API they would need some sort of SDK?
One approach would be to set the Constants.FRAMEWORK_BUNDLE_PARENT framework launch property to your application class loader and the Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA framework launch property to the list of packages that you want to expose to plugins. The plugins would then use Import-Package in their bundle manifest for your application's packages in the same way as any other package.
I want to make a java application that supports plug ins. Now my core will use jars for certain processes. If my plug ins where to also use these jars, do the plug ins of my application need to configure their build path to include the jars they would also use or is their a way so that the jars can be imported similar to how I import packages from the main application
Guice and Spring are tools for dependency injection, which means that creating objects is easier with them because they take care of instantiating objects and placing them into other objects that depends on them.
Now, when we talk about plugins, we usually are talking too about dynamically loading new classes into a running app. Think on eclipse IDE. Its architecture was designed from the beginning to be "pluggable", like, you can download jars and eclipse will add them to the running application without the need of application restart.
In this case, if you want to build pluggable apps, in a sense of dynamic classloading, I'd recommend you not to go through this path, but to research subjects such as OSGI. One popular OSGI framework is http://felix.apache.org/
Another approach for application extension (we may call this pluggable too, somehow, I guess), depending on how your app is organized and what it does, is to develop a DSL (http://en.wikipedia.org/wiki/Domain-specific_language) for it and extend it letting people adding scripts to it. Isn't something like this when a browser let you add pieces of funcionality written in javascript? Groovy makes DSL easier in some aspects, for java programmers. (see http://docs.codehaus.org/display/GROOVY/Writing+Domain-Specific+Languages)
If you want dynamic plugable systems OSGI can give you this, but OSGI its IMMO a over-complicated technology, use only if you are really sure that needs this dynamic plug-ability.
Other option for builds extensible systems its use de ServiceProvider mechanism, this is a core java mechanism, for example its the one that JDBC implementations use, you can put a JDBC driver in your classpath and the application can find it and use it without needing that you explicitly import the driver classes in your code.
This is an example of using ServiceProvider in your owns applications: http://docs.oracle.com/javase/tutorial/ext/basics/spi.html#limitations-of-the-service-loader-api
Its of course more limited than OSGI, but its very easy to use when you get the idea, and you don't need any external library because its a java core mechanism.
EDIT: about the libraries.
In runtime: With ServiceProvicer there is no separate classloaders (you can implement off course, but by default, in OSGI its implemented this separation), in runtime if your plugin need X class and this class is in the classpath all is ok, the limitation its that the main application and all the plugins use this version of the dependency (guice 3 for example) and you cannot have one plugin using X version and other plugin using X+2 version if this version are not compatible. (this is the famous hell .jar, and one of the principal motivations behind jigsaw project for example).
In compile time, include the dependency in your pom, ant build file, gradle build file or whatever build system your use as usual.
My application utilizes many libraries that each require their own configurations.
For example, both Hibernate and Apache Shiro requires me to specify database connection details in the configuration files of each library. Is there any method of centralizing these values into a single file, XML or otherwise, that would make it a lot easier to manage?
In this situation, you can either
configure the libraries programatically, without configuration files, using a common framework. e.g. Spring.
generate the configuration files using templates for each configuration file and a shared set of properties.
There is no universal solution. Each library (typically) has its own way of doing configuration that isn't conducive for sharing with other libraries.
If you were using Spring DI, then there is considerable scope for sharing configuration via Spring XML wiring files ... provided that the library is configurable that way. (The latter means that you need to be able to inject the configuration information; e.g. as a Properties object.)
Another possibility is to use something else to generate your configuration files; e.g. Chef or Puppet ... or old fashioned macros.
I'm creating a Java web application, making use of CDI. My War includes various Jar files that are bean sources (including the META-INF/beans.xml file). My beans are automatically discovered when running inside a Java EE container like JBoss (I'm currently using JBoss AS 7.1.1). This much is working well.
I want to be able to extend the web application, ideally by allowing it to load classes from Jar files stored in a configurable location (so at a location specified by a system property). This too is fine, since I can use a ClassLoader to resolve classes and resources. What I'm missing is the ability to have CDI scan these external Jar files and include their beans.
This would allow my application to host plug-in functionality including new REST resources. I don't mind if I had to restart the application for it to pick up classes and resources contained within these external Jar files.
I can see no way of achieving this. Is this even something that should be attempted in this kind of environment?
I can see no way of achieving this.
You actually have two options:
Use the CDI extension mechanism to work with beans / bean-archives
at startup time and to modify them in the way you want. Have a look at the examples provided in the documentation, this should give you a start.
Work with the BeanManager at execution time. Have a look at this similar question.
I like OSGi, but the import/export restrictions and the lack of context class loader creates havoc when trying to use 3rd party libraries (e.g., some libraries try to find file.xml in META-INF, expecting for all such files in all jars to be returned, other libraries use ServiceLoader).
I want OSGi's dynamic loading, ability for handling several versions of the same library, and service framework.
So what are my alternatives? I know of JPF, looking for something less xmlish.
I had this problem with having a java mail bundle separate from my java activation bundle. You have the following options to get 1 bundle to see files (ie. not java resources but things like xml files) in META-INF of other bundles.
1) Merge the bundles together. This is often icky to deal with or just not impossible for the project.
2) Have the bundles that need to share resources be bundle fragments of the bundle that needs to read up the resources. Bundle fragments are defined by the OSGi spec and allow separate bundles to share resources as though they were merged together.
Have you tried googling for each library + osgi? A quick glance shows some others experiences and (it would seem) successes.
Sorry for the "just google it answer" but since I don't actively use these libraries in my OSGi app I can only suggest how I've handled this for some of my libraries ... which was google.
This is not really a good answer, but I don't want this buried in comments.
I want OSGi's dynamic loading, ability for handling several versions of the same library, and service framework.
There are other service frameworks, but to get dynamic loading and several versions of the same class there is nothing else by OSGi that I know of.
Also, now that OSGi seems to finally gain some traction, the pressure on libraries to "play nice" is rising. SpringSource for example maintains a growing collection of OSGified libraries. The package you need may already be there.