Add Custom Mediator (Java Class) without restart - java

We often have Custom Mediators (Java classes) that are performing transformations or other things. Each time we want to change only one little thing inside the class, we need to restart the whole WSO2 ESB.
May the "custom mediator" approach is wrong, but we'd like to keep the java classes, but de-coupled from the whole server - like proxies or endpoints. (Our classes are inside a .jar in /components/lib)
How can a custom mediator or java class added to the WSO2 ESB without restarting?
<class name="my.domain.MyJavaClassThatMustBeUpdatedWithoutRestart"/>

You can create an osgi bundle from your class and then you can control the classes behavior from the OSGI Console. You need to start esb with -DosgiConsole option. You can find more information from this blog post.
http://lalajisureshika.blogspot.co.uk/2013/03/some-useful-osgi-commands-to-find.html

While starting up we make OSGI bundles out of the non-OSGI jars in components/libs.
So you must restart if you want to change the custom mediator jars.
As per the below coment explaining the answer,
WSO2 Products are running on an OSGI based platform. So if you change an OSGI bundle you can restart the bundle from the OSGI Console without restarting the whole server. Also the OSGI Container used by WSO2 is Eclipse Equinox OSGI Container. It provides the ability to add non-OSGI jars to product with the feature of, converting those jars in to OSGI Bundles. And that feature works only at the server startup. So if you want to add/change those jars you should restart the server. In runtime you can change OSGI bundles, but you can not convert non-OSGI bundeles to OSGI in runtime.

Related

Deploying war into OSGI at Runtime

My requirement is to deploy war files into OSGI at runtime.
For to achieve that I am trying through below codes:
BundleContext bundlecontext = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
Bundle b = bundlecontext.installBundle("file:" + "./war/testwar.war");
b.start();
But I am unable to achieve that, by using the above codes.
As I am new to OSGI I have very less idea of OSGi.
So I need help on this to achieve.
OSGi runtime is not an application server but environment that manages modules (bundles). A war is not (usually) an OSGi bundle and can not be installed the way you do it.
There are many different ways to achieve what you want and it's hard to suggest something. Here are some of the them:
Convert the WAR to WAB (Web Application Bundle). This way you can install it into any OSGi runtime. You would also need to install other bundles that can handle web requests (HTTP Whiteboard implementation for example)
Use an OSGi based product that can automatically convert wars to bundles. Liferay Portal does that but it may be too much to learn it if all you want is to run one app.
If you tagged the question with apache-karaf because that is your environment, then have a look at War deployer. That feature will allow you to install war files in Karaf. If you want to do it from code, you can have a look at the code of that feature and follow the same approach.

JSP and OSGi: bundling css and javascript

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

Best way for sharing of domain objects across Eclipse plugins?

I am making a set of Eclipse Plugins for the Eclipse Workbench.
I want these Eclipse Plugins to communicate with each other through some shared
data structures/managers.
Is there some bootstrapping or other initialization process wherein I
can pass the shared domain objects through the constructor for the plugins(depepndency injection)?
What is the standard and best practice for achieving sharing of data across plugins?
Eclipse is OSGi based using the equinox runtime. OSGi manages all of the runtime dependencies you need.
The simplest way is to deploy your common code as a bundle (plugin). Export all of the packages you need to other plugins. (Export-Package header in manifest.mf)
In the plugins you need the package, declare them as imported packages (Import-Package in the manifest.mf file)
If you want to go the extra mile, expose the managers you need as services, and add service consumers in the plugins you need.
Here's a simple tutorial to using services:
http://www.knopflerfish.org/osgi_service_tutorial.html

JDBC/OSGi and how to dynamically load drivers without explicitly stating dependencies in the bundle?

This is a biggie.
I have a well-structured yet monolithic code base that has a primitive modular architecture (all modules implement interfaces yet share the same classpath). I realize the folly of this approach and the problems it represents when I go to deploy on application servers that may have different conflicting versions of my library.
I'm dependent on around 30 jars right now and am mid-way though bnding them up. Now some of my modules are easy to declare the versioned dependencies of, such as my networking components. They statically reference classes within the JRE and other BNDded libraries but my JDBC related components instantiate via Class.forName(...) and can use one of any number of drivers.
I am breaking everything up into OSGi bundles by service area.
My core classes/interfaces.
Reporting related components.
Database access related components (via JDBC).
etc....
I wish for my code to be able to still be used without OSGi via single jar file with all my dependencies and without OSGi at all (via JARJAR) and also to be modular via the OSGi meta-data and granular bundles with dependency information.
How do I configure my bundle and
my code so that it can
dynamically utilize any driver on the
classpath and/or within the OSGi
container environment
(Felix/Equinox/etc.)?
Is there a run-time method to detect if I am running in an OSGi container that is compatible across containers (Felix/Equinox/etc.) ?
Do I need to use a different class loading mechanism if I am in a OSGi container?
Am I required to import OSGi classes into my project to be able to load an at-bundle-time-unknown JDBC driver via my database module?
I also have a second method of obtaining a driver (via JNDI, which is only really applicable when running in an app server), do I need to change my JNDI access code for OSGi-aware app servers?
Utilizing any driver within the OSGi environment requires you using a DynamicImport-Package: * statement so your bundle can resolve these packages when you load a driver with Class.forName(..).
Probably the easiest way is to try to access a class that is in the org.osgi.framework package. Those should at least be always around in an OSGi environment (see snippet below). There are more sophisticated mechanisms, so let me know if you need something more advanced. Also, take a look at the OSGi R4.2 core spec, paragraph 3.8.9 which shows some methods of finding the Bundle and BundleContext of a class and therefore indirect helps in determining if you're in a framework or not.
That depends on what you're doing, no generic "yes" or "no" answer here. OSGi uses classloaders and does so in a way that is not "typical" for a standard Java application, but depending on what you're doing, you might not notice.
No.
Take a look at the recently released OSGi enterprise specs. They have a chapter on JNDI integration in OSGi which probably allows you to leave your code (largely) unmodified.
A simple example snippet:
public static boolean inOSGi() {
try {
Class.forName("org.osgi.framework.FrameworkUtil");
return true;
}
catch (ClassNotFoundException e) {
return false;
}
}
Just make sure that you if you put this code in a bundle, the bundle should import org.osgi.framework (otherwise it will never find that class).
I made a JDBC driver manager for OSGI in an Eclipse RCP and I will take you through how to play nice with OSGI. First, forget about DynamicImport-Package, the only good way to use OSGI is to install/start/stop bundles and use the OSGI mechanism the way it was designed.
You have your JDBC bundle, and create another "Driver bundle" which has the initialization of the DriverClass, the Connection logic and add the necessary commons libraries such as dbcp2 and pool2.
Export the Driver bundle as a JAR/ZIP and include it in your JDBC bundle as a resource.
Let your JDBC bundle unzip the Driver bundle in its work area.
String workdir= Platform.getStateLocation(jdbc_bundle).toPortableString();
Programmatically add driver jars and modify the Driver bundle's MANIFEST.MF file accordingly.
Load the Driver bundle programmatically from the work area
getBundleContext().installBundle("file:/"+workdir);
Use bundle.start(), stop(), uninstall() as necessary when programmatically modifying the list of drivers.
The pax-jdbc can be used to delegate dataSources via declarative way, means you can create a config entry in ConfigAdmin service, and the dataSource can be accessed via JNDI. The JDBC driver is deployed as bundle. (most of them have OSGi version)
For example:
The config entry PID is org.ops4j.datasource-test
Properties:
osgi.jdbc.driver.name=H2
databaseName=test
user=sa
password=
dataSourceName=testds-h2
The service is identified by the given dataSourceName. So you can filter for it with (&(objectClass=javax.sql.DataSource)(dataSourceName=test2)).
And you can access the datasource via JNDI:
osgi:service/javax.sql.DataSource/(osgi.jndi.service.name=test2)

Dynamic loading of modules in Java

In Java, I can dynamically add stuff to classpath and load classes ("dynamically" meaning without restarting my application). Is there a known framework/library which deals with dynamic loading/unloading of modules without restart?
The usual setup, especially for web-apps, is load balancer, several instances of application, and gradual deployment and restart of new version. I'm looking for something else - application with several services/plugins, possibly single-instance desktop application, where disabling single service is cheap, but bringing down or restarting complete application is not feasible.
I'm thinking about typical plugin infrastructure, where plugins can be upgraded or installed without restarting application. Do I have to program that from scratch, or is something already available? Spring-compatible and opensource is a plus, but not a requirement.
You might consider running your spring application in an OSGI framework.
I believe the DMServer is a module-based Java application server that is designed to run enterprise Java applications and Spring-powered applications, based on OSGI
You can find more details in this Hello, OSGi, Part 2: Introduction to Spring Dynamic Modules article, in particular how to use Spring DM to dynamically install, update, and uninstall modules in a running system.
Note: when you speak about "plugins can be upgraded or installed without restarting application", OSGI is the first candidate framework that comes to mind.
It is all about modularization of applications into smaller bundles.
Each bundle is a tightly-coupled, dynamically loadable collection of classes, jars, and configuration files that explicitly declare their external dependencies (if any).
Perhaps the simplest approach is to load each plugin with it's own class loader. Then discard the class loader and create a new one to reload the plugin. You will want init() and destroy() methods in the plugin API to allow a chance for startup/shutdown type functionality.
This also has the advantage of isolating the plugins from each other.
A URLClassLoader is your starting point for this. The general idea is that you provide a XxxPlugin superclass that any plugin subclasses. Consider the example of Applet, which is essentially a GUI plugin (or Midlet, etc).

Categories

Resources