How to extend / amend OSGi lifecycle management? - java

I have a modular application that uses OSGi for lifecycle and dependency management. However, some of the bundles require some time after startup to be ready, for example, because they have to acquire data from somewhere. Also, they might be unable to process certain calls during a configuration update, for example a bundle that keeps a connection to a db can't send queries while it is updating the connection parameters.
So, it seems to me that a bundle can have more subtle states than those managed by the OSGi container, and since they affect bundle interaction, there needs to be some handling. I can see three basic strategies for doing this:
screw subtlety, and for example put all initialization code into BundleActivator.start(). If it takes forever to acquire that data, well then the bundle just won't be started forever. I'm not 100% sure that this would cover all cases, and it seems slightly wrong.
fit my bundles with an additional event system that they use to notify each other of more subtle states like "momentarily unavailable" or "really ready now". This might simply be unnecessary overhead.
have the bundle keep its more subtle state changes to itself and just take calls anyway, deferring them internally if necessary. This might not be appropriate when the caller could actually handle unavailability better.
Do you have any general advice on that? Is there even something in OSGi that I could use?

Try using services and service tracker to communicate between bundles. This will also help decouple your bundles as you'll likely be using interfaces.
Using you example of bundle which talks to a database:
Activator.start(), launch a background thread to do your initization business. Activators should execute quickly.
Register a service that provides the needed DB related abstraction for other bundles.
Other bundles create a service tracker to look for services they need,
Other bundles get a callback in the service tracker only when the first bundle registers the service. The first bundles only registers the service when it's ready implying that other bundles can begin using it immediately.

Related

Osgi bundles and their relation with packages

For an application written using OSGi specifications
A service is a java object that represents a feature, recording a voice call for example
Every service has a number of packages associated with it, for example, service interface, service implementation, and slick.
I can't get the relation between the above and OSGi bundles, as bundles contain services does that mean they contain the service packages or something else
An OSGi service is a mechanism for bundles to communicate over a well defined Java interface known to all parties. OSGi acts as a broker where one party can register a service under the interface name, and other parties can get it under this interface name. I.e. the actual implementation class is decoupled from the users of the service. This allows the use of different implementation classes while the user of the service is unaware. I.e. for example, if you want to set up a voice call, there could be an PhoneExchange service that would provide you with the functions to setup the call and maybe record it. You can then write your code against the PhoneExchange interface. In runtime, you might be coupled to an Ericsson PBX or a Nokia one.
This decoupling is also present with Java factories. However, Java factories have many disadvantages, and tend to be very static. The OSGi broker is a dynamic broker. A service can be registered but also unregistered. The dynamism in OSGi is seen by many as hard to handle but the Declarative Services makes that more or less trivial. When you really get the dynamism of OSGi services you will find out that many complex dynamic scenarios, like for example communication channels, map extremely well.
The bundle is the module in OSGi. It contains all the Java code and resources. A bundle will export and import Java packages. In a well designed system, these are only the Java packages that hold the service interfaces. It is a bad pattern to export implementation packages. At startup, bundles are wired. This means that exporters get bound to importers. OSGi is unique in that it can handle the same package in multiple versions.
Bundles have their own life cycle. They get started and stopped. In both cases, they can run their own private code.
The aforementioned Declarative Services provide yet another layer. When a Java class declares it is a component with an annotation, it can also declare on what services it depends. When these services are registered, they are injected and the component is activated. Declarative Services allow you to eat your cake and have it to. You get the incredibly powerful dynamics without the associated complexity.

Share object between JavaEE applications on the same JVM (using JNDI)

I'm running a JBoss AS 7.1.3.Final installation with a lot of applications. One of those applications provides common resources and functionallities used by all applications (let's call it framework). I'm also planning to move to WildFly 8, if this is an useful information for your answer.
All applications should only be accessible, if the framework is available (up and running). My current implementation to achive this dependency is not that nice** and as I'm currently re-designing some parts of the environment, I'm looking for a much neater solution for it. My first idea was to create some kind of a manager which will be instantiated by the application server and is available to all applications. So after an application is started, it could register itself on the manager and as soon as the framework is up, the applications will be notified.
Is this possible using the JNDI of the JVM where all applications + framework are running? How must this be implemented? It's really hard to find useful information about how the JNDI works and what is possible with it. Do you have any other, simplier ideas, how to share a class instance between applications?
Thank you.
** Currently I'm using a EJB-timer in the applications and a singleton EJB in the framework. The framework is available as soon as the EJB lookup succeeds.
--
Edit #1
Some more informations as requested by Nikos Paraskevopoulos
One functionionality that is provided by the framework is the maintenance mode. The applications will check, right after startup, if it is blocked for normal users. It will also receive notifications about planned maintenances. (central DB, the application has no rights on it)
Common stylesheets or layouts are deployed with the framework.
The user informations are provided by the framework. (central DB, the application has no rights on it)
The main problem is: How could I avoid any timers? I have no idea, how I could ensure, that the framework is up before everything else.
A few thoughts:
JBoss has the capability of ordering deployments according to their dependencies. See here and here. So, if all the "applications" depend explicitly on the "framework", your problem may be solved.
It seems you have a quite strongly coupled configuration. Would it be possible to decouple them, e.g. provide the service through web services (SOAP/REST)? Of course this introduces extra overhead for the communication and the refactoring...
JNDI can be seen (very roughly) as a name to object map shared across the applications. As such, you may share stuff through it. But I do not see how will you solve the timing problem, i.e. wait for a service to be available before using it from the "applications". The manager component you mention can be placed in JNDI.
This is not a complete answer, but it would not fit as a comment either. Maybe if you presented more details on the nature of the applications, the frameworks used etc, you could get more specific answers.
Good luck anyway
Edit #1:
Maintenance mode: This may be nice for using with JNDI. A servlet filter that intercepts every (applicable) request will check a global JNDI name; if it is not found (i.e. framework not started) or it is false, it will short-circuit the processing of the request, sending back the "maintenance mode" page. The framework will have to set a Boolean in the global JNDI name as soon as it has started and maintain its value, i.e. set it to false if maintenance mode is active.
Common stylesheets: This is really covered by the maintenance mode flag, I believe. Layouts: It depends on the view technology/layouts technology.
User information: This is a good candidate for SOAP/REST implementation. It is not expected to be called frequently, so I assume overhead will not matter.
I think OSGi is the technology you should consider. Basically you have an OSGi container with applications (called bundles) which provide or consume services. So you would have a framework service which is consumed by all applications. JBoss is an OSGi container, as far as I know.

Java enterprise architecture for delegating tasks between applications

In my environment I need to schedule long-running task. I have application A which just shows to the client the list of currently running tasks and allows to schedule new ones. There is also application B which does the actual hard work.
So app A needs to schedule a task in app B. The only thing they have in common is the database. The simplest thing to do seems to be adding a table with a list of tasks and having app B query that table every once in a while and execute newly scheduled tasks.
Yet, it doesn't seem to be the proper way of doing it. At first glance it seems that the tool for the job in an enterprise environment is a message queue. App A sends a message with task description to the queue, app B reads a message from the queue and executes the task. Is it possible in such case for app A to get the status of all the tasks scheduled (persistent queue?) without creating a table like the one mentioned above to which app B would write the status of completed tasks? Note also that there may be multiple instances of app A and each of them needs to know about all tasks of all instances.
The disadvantage of the 'table approach' is that I need to have DB polling.
The disadvantage of the 'message queue approach' is that I'm introducing a new communication channel into the infrastructure (yet another thing that can fail).
What do you think? Any other ideas?
Thank you in advance for any advice :)
========== UPDATE ==========
Eventually I decided on the following approach: there are two sides of this problem: one is communication between A and B. The other is getting information about the tasks.
For communication the right tool for the job is JMS. For getting data the right tool is the database.
So I'll have app A add a new row to the 'tasks' table descibing a task (I can query this table later on to get list of all tasks). Then A will send a message to B via JMS just to say 'you have work to do'. B will do the work and update task status in the table.
Thank you for all responses!
You need to think about your deployment environment both now and likely changes in the future.
You're effectively looking at two problems, both which can be solved in several ways, depending on how much infrastructure you able to obtain and are also willing to introduce, but it's also important to "right size" your design for your problems.
Whilst you're correct to think about the use of both databases and messaging, you need to consider whether these items are overkill for your domain and only you and others who know your domain can really answer that.
My advice would be to look at what is already in use in your area. If you already have database infrastructure that you can build into, then monitoring task activity and scheduling jobs in a database are not a bad idea. However, if you would have to run your own database, get new hardware, don't have sufficient support resources then introduction of a database may not be a sensible option and you could look at a simpler, but potentially more fragile approach of having your processes write files to schedule jobs and report tasks.
At the same time, don't look at the introduction of a DB or JMS as inherently error prone. Correctly implemented they are stable and proven technologies that will make your system scalable and manageable.
As #kan says, use exposing an web service interface is also a useful option.
Another option is to make the B as a service, e.g. expose control and status interfaces as REST or SOAP interfaces. In this case the A will just be as a client application of the B. The B stores its state in the database. The A is a stateless application which just communicates with B.
BTW, using Spring Remote you could expose an interface and use any of JMS, REST, SOAP or RMI as a transport layer which could be changed later if necessary.
You have messages (JMS) in enterprise architecture. Use these, they are available in Java EE containers like Glassfish. Messages can be serialized to be sure they will be delivered even if the server reboots while they are in the queue. And you even do not need to care how all this is implemented.
There can be couple of approaches here. First, as #kan suggested to have app B expose some web service for the interactions. This will heterogenous clients to communicate with app B. Seems a good approach. App B can internally use whatever persistent store it deems fit.
Alternatively, you can have app B expose some management interface via JMX and have applications like app A talk to app B through this management interface. Implementing the task submission and retrieving the statistics etc. would be simpler. Additionally, you can also leverage JMX notifications for real time updates on task submissions and accomplishments etc. Downside to this is that this would be a Java specific solution and hence supporting heterogenous clients will be distant dream.

Controlling timed execution in Spring-based Pojo in Java EE

I'd like to have a Spring-managed bean schedule execution of itself (or some other bean, simple factoring) if certain conditions are met (i.e. checking successul startup etc.)
I'd also like to be able to see and control the timer from within the application, which will be running on a Java EE 5-compliant container.
Not sure how best to do this - I know about the dangers of doing thread management myself in an EE environment.
You could have a base class that is a wrapper to schedule background tasks (could be e.g. an Executor or TimerTask) and be parameterized by the timing intervals or even the task to schedule and you could derive more specific classes specialized on certain tasks.
These you would configure/instantiate via Spring configuration and of course your app could modify these via the properties of the classes/beans.
Concerning thread management, I also had concerns regarding threads since JavaEE specs (I believe specifically EJB specs) disallow it but this perhaps depends on the container. For example in Tomcat which of course is not a fully EE container, I never had issue with my own threads.
You don't mention which container you are interested in.
Also (friends here can correct if I am wrong) my understanding is that threads are disallowed e.g. in EJB containers etc if you access various resources handled by the container threads.
So if you only want to do some e.g. sanity checks (checking succesful startup) and similar, I don't think that this would be an issue. But this is MHO. I am not sure to be honest

Service References in OSGi

Once an instance of an OSGi service is retrieved from the bundle context does it become invalidated when the service is stopped?
My initial tests show that the service instance can be used even after the service bundle is stopped, which contradicts my understanding of the dynamic nature of OSGi.
I suppose this boils down to what retrieving a service (via ServiceTracker) from another bundle in the OSGi container actually does, does it create a new instance or does it give you a pointer to the instance that is registered in the container?
Are there any dangers in using the service instance after the service has been stopped?
This is a very good question so I digged into the specification in search for a definitive answer. It turns out that there is a whole section talking about this problem - see section 5.4 Stale References starting on page 132 of OSGi Service Platform Core Specification, Release 4, Version 4.2.
To answer your question according to the specification:
The behavior of a service that becomes unregistered is undefined. Such services
may continue to work properly or throw an exception at their discretion.
And to prevent potential problems:
Bundles must listen to events generated by the Framework to clean up and remove stale
references.
The specification also gives some tips how to minimize the consequences of stale references.
You are right in that it is contradictory to the dynamic nature of OSGi. I believe that there is no guarantee that the service will be available, although different implementations of OSGi containers and services themselves may behave differently.
For example, if the service was created and registered with Spring DM, then the service retrieved is actually a Spring based proxy to the underlying implementation, and the implementation can still disappear. Thus a service reference that refers directly to an implementation may keep that object from being removed, whereas the proxy based reference will not.
The OSGi specification says:
Bundles are entities that are visible
in normal application programming. For
example, when a bundle is stopped, all
its services will be unregistered.
So you shouldn't be able to get a service from a stopped bundle. But technically it may be possible to use it, at least as long as you hold a reference to the service object (nobody can take it away from you and it will not be GC'd). But I don't think that it is save to use the service. It may depend on other bundle resources, that are not available after the bundle has stopped.
Once an instance of an OSGi service is
retrieved from the bundle context does
it become invalidated when the service
is stopped?
No, the reference itself does not become invalidated. As long as something within the container is holding it, it can also not be GC'ed.
However, whether or not it will be still useful, depends only on the service implementation itself, not the container.
My initial tests show that the service instance can be used even after the service bundle >is stopped, which contradicts my understanding of the dynamic nature of OSGi.
The specifications itself indicate that such references shouldn't be held, but it's up to the implementer to take care for implementing the specifications correctly; means there is no contradiction, there is only the fact that you can implement and deploy bundles which don't behave correctly according to the specifications.
I suppose this boils down to what retrieving a service (via ServiceTracker) from another bundle
in the OSGi container actually does, does it create a new instance or does it give you a pointer
to the instance that is registered in the container?
The container does not create new instances of services, except if there is a ServiceFactory involved (see specs). Looking up a service should always give you a pointer to the registered instance in the container.
Are there any dangers in using the service instance after the service has been stopped?
That only depends on the service implementation; however, by doing so in a bundle, you automatically create a bundle that is not conform with the specs.
In practice, many services are implemented to release resources and references and will not respond properly any longer.
Regarding your question whether it is dangerous to use a service instance after the service has been stopped. To cite from the 4.2 core spec (5.4 Stale References):
The behavior of a service that becomes
unregistered is undefined. Such
services may continue to work properly
or throw an exception at their
discretion.
I dont want to cite the whole section of the spec here, but the following sentences are a good discussion about the danger of using stale references:
A stale reference is a reference to a Java object that belongs
to the class loader of a bundle that is stopped or is associated
with a service object that is unregistered. Standard Java does not
provide any generic means to clean up stale references, and bundle
developers must analyze their code carefully to ensure that stale
references are deleted.
Stale references are potentially harmful because they hinder the Java
garbage collector from harvesting the classes, and possibly the instances,
of stopped bundles. This may result in significantly increased memory
usage and can cause updating native code libraries to fail. Bundles using
services are strongly recommended to use either the Service Tracker or
Declarative Services.
A service reference should never be kept as a reference. You should always look up a service at runtime. This ties you to the OSGI api however, whihc is not always wanted.
Have a look at
- OSGI serviceTracker
- OSGI declarative services
- OSGI BluePrint
- Spring DM
- Peaberry
- iPojo
which all take care of the dynamism for you, most of them with no OSGI api to use.
Regards,
Leen Toelen

Categories

Resources