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

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.

Related

OSGi: how to securely share connection between bundles

I am trying to develop a java software based on OSGi (Apache Felix), which different module (which may contain more than one jar file) could be developed by different developers from different companies.
the question is: i am wondering how should i provide database connection to these modules. if i share the same user credential between modules, they may accidentally or intentionally use each other tables or data which should be avoid because of information privacy. or if i force each module to have its own connection with its own user credential then there will be many connections.
note: i am using mariadb as backend.
i know this problem is not a OSGi specific problem. i am wondering if anyone has faced such problem and has proven solution for this scenario (i only describe my development environment).
any idea,
thanks
First of all, your issue of multi-tenancy isn't something any system (beeing it OSGi or not) is made for. Therefore you need to take care of this yourself. Most OSGi applications still use datasources if you want to connect to a db, via JPA for example. Usually those datasources are registered as OSGi services.
Coming back to your multi-tenancy issue, you should make sure for each you have another datasource and just use that datasource in your application. For example make sure each tenant has it's own configuration and therefore receives his own Datasource as configured in your configuration. This way you can make sure each tenant is separate to each other.
OSGi cannot achieve the level of security you need for this scenario. An OSGi Framework is intended to represent a single logical application. If bundles exist in the same JVM and OSGi Framework, then it is very hard to prevent data leaks, especially against determined attacker.
You need to isolate processes at the very least, and run those processes as separate user IDs.

Any properties needs to be changed for multi user application

Please consider me as a novice and this is my first web app I am creating.
I am planning to develop a web application where the traffic I am expecting is around 50 users will access the application at a single time.
The webapp is developed with Vaadin (for UI) and respective business logic implemented with Java. DB used would be MySQL. The war will be deployed in Tomcat.
So, my question is do I need to modify anything in Tomcat properties or anywhere to make the web app as multi user application (i.e. each users need to access and use application as though they are only one using the application)?
I tried to access a prototype developed using Vaadin in both Chrome and Firefox and could see both sessions running without an impact on another.
But please let me know suggestions.
You must keep in mind that even if tomcat and vaadin manage multiple sessions, your server application will have only 1 instance. So if you use singletons, static methods or fields, use them with care: they should never hold session-dependant content. Try to favour stateless methods over statefull.
Apart from that, there shouldn't be any problem.
It should not have any code changes if you handle the session and your business logic with statefulness properly.
There might be some configuration changes, like increasing the database connection pool size, it depends on what kind of connection pooling you are using and what is the default size etc.
Apart from that it should work just fine.
Vaadin is built on top of Jakarta Servlet technology (formerly known as Java Servlet). See Wikipedia. Indeed, Vaadin is a servlet, a much bigger and more sophisticated servlet than most.
Within a Java Servlet container (engine) such as Apache Tomcat or Eclipse Jetty, any particular servlet has only a single instance running. If three requests from three users arrive at the same time, there are three threads running through that same single instance for that particular servlet. So a servlets are inherently a highly threaded environment.
If you share any variables or resources between those threads, you must be very careful. That means mandatory reading, rereading, and fierce study of the book Java Concurrency in Practice by Brian Goetz, et al.
While the Web and HTTP were designed to be stateless delivery of single documents, that original vision has been warped by the desire to make web apps. To maintain state, a servlet automatically maintains a session. Vaadin represents this session state in its VaadinSession object. All data in all the forms, along with business logic, running for each user is maintained as part of that session.
Depending on your particular Vaadin app, and when multiplied by the number of concurrent users, this may add to a large amount of memory. You should monitor your server to make sure you have enough available RAM on your server.
do I need to modify anything in Tomcat properties or anywhere to make the web app as multi user application (i.e. each users need to access and use application as though they are only one using the application)?
No, nothing for you to set or enable. Tracking the requests/responses and session for each user is the very purpose of a servlet container. From the moment it launches, every servlet container expects multiple users. As a Servlet, Vaadin is built to expect multiple users as well. The only trick is making your own code thread-safe, hence the book suggestion.
I tried to access a prototype developed using Vaadin in both Chrome and Firefox and could see both sessions running without an impact on another.
Concurrency problems can be very tricky to detect and debug. Often potential problems occur on the random chance of coincidental timing. You need to focus on properly designing your code in the first place, rather than relying on testing. Again, hence the book recommendation.
Of special note, since you mentioned using a database, is JDBC drivers. Deploying them in a Servlet environment can be tricky. Basically you need to not bundle them within your Vaadin web app WAR file. Instead, deploy the JDBC driver separately within a shared library folder within Tomcat. If using Maven to drive your project, direct Maven in the POM file to give the dependency for your JDBC driver a scope of provided. This has nothing to do with Vaadin specifically, it applies to all servlets. Search Stack Overflow as this issue has been extensively addressed.

Spring MVC with JBoss vs Tomcat - Advantages / Practice

Okay. This is again a question of industry practice.
Tomcat = Web Container
JBoss, WebLogic, etc = Application Servers that have Web Container within (for JBoss, its forked Tomcat)
Spring does not need Application Server like JBoss. If we use enterprise services like JMS, etc we can use independent systems like RabbitMQ, ApacheMQ, etc.
Question is why do people still use JBoss and other Application Serves for purely spring based applications?
What are the advantages Spring can make use of, by using Application Servers? Like object pooling? What specific advantages does Application Server offers? How are those configured?
If not for spring, for what other purposes Application Servers are used for Spring/Hibernate, etc stack? (Use cases)
Actually I would say listening for JMS is probably the best reason for an application server. A stand alone message broker does not fix the problem since you still need a component that's listening for messages. The best way to do this is to use a MDB. In theory you can use Springs MessageListenerContainer. However this has several disadvantages like JMS only supports blocking reads and Spring therefore needs to spin up it's own threads which is totally unsupported (even in Tomcat) and can break transactions, security, naming (JNDI) and class loading (which in turn can break remoting). A JCA resource adapter is free to do whatever it wants including spinning up threads via WorkManager. Likely a database is used besides JMS (or another destination) at which point you need XA-transactions and JTA, in other words an application server. Yes you can patch this into servlet container but that this point it becomes indistinguishable from an application server.
IMHO the biggest reason against application servers is that it takes years after a spec is published (which in turn takes years as well) until severs implement the spec and have ironed out the worst bugs. Only now, right before EE 7 is about to be published do we have are EE 6 servers starting to appear that are not totally riddled with bugs. It gets comical to the point where some vendors do no longer fix bugs in their EE 6 line because they're already busy with the upcoming EE 7 line.
Edit
Long explanation of the last paragraph:
Java EE in a lot of places relies on what's called contextual information. Information that's not explicitly passed as an argument from the server/container to the application but implicitly "there". For example the current user for security checks. The current transaction or connection. The current application for looking up classes to lazily load code or deserialize objects. Or the current component (servlet, EJB, …) for doing JNDI look ups. All this information is in thread locals that the server/container sets before calling a component (servlet, EJB, …). If you create your own threads then the server/container doesn't know about them and all the features relying on this information don't work anymore. You might get away with this by just not using any of those features in threads you spawn.
Some links
http://www.oracle.com/technetwork/java/restrictions-142267.html#threads
http://www.ibm.com/developerworks/websphere/techjournal/0609_alcott/0609_alcott.html#spring-4
If we check the Servlet 3.0 specification we find:
2.3.3.3 Asynchronous processing
Java Enterprise Edition features such as Section 15.2.2, “Web Application Environment” on page 15-174 and Section 15.3.1, “Propagation of Security Identity in EJBTM Calls” on page 15-176 are available only to threads executing the initial request or when the request is dispatched to the container via the AsyncContext.dispatch method. Java Enterprise Edition features may be available to other threads operating directly on the response object via the AsyncContext.start(Runnable) method.
This is about asynchronous processing but the same restrictions apply for custom threads.
public void start(Runnable r) - This method causes the container to dispatch a thread, possibly from a managed thread pool, to run the specified Runnable. The container may propagate appropriate contextual information to the Runnable.
Again, asynchronous processing but the same restrictions apply for custom threads.
15.2.2  Web Application Environment
This type of servlet container should support this behavior when performed on threads created by the developer, but are not currently required to do so. Such a requirement will be added in the next version of this specification. Developers are cautioned that depending on this capability for application-created threads is not recommended, as it is non-portable.
Non-portable means it can may in one server but not in an other.
When you want do receive messages with JMS outside of an MDB you can use four methods on javax.jms.MessageConsumer:
#receiveNoWait() you can to this in a container thread, it doesn't block, but it's like peeking. If no message is present it just returns null. This isn't very well suited for listening to messages.
#receive(long) you can to this in a container thread, it does block. You generally don't wan't to do blocking waits in a container thread. Again not very well suited for listening to messages.
#receive(), this blocks possibly indefinitely. Again not very well suited for listening to messages.
#setMessageListener() this is what you want, your get a callback when a message arrives. However unless the library can hook into the application server this won't be a container thread. The hooks into the application server are only available via JCA to resource adapters.
So yes, it may work, but it's not guaranteed and there are a lot of things that may break.
You are right that you don't really need a true application server (implementing all Java EE specs) to use Spring. The biggest reason people don't use true Java EE apps like JBoss is that then have been slow as #$##% on cold start up time making development a pain (hot deploy still doesn't work that well).
You see there are two camps:
Java EE
Spring Framework.
One of the camps believes in the spec/committee process and the other believes in benevolent dictator / organic OSS process. Both have people with their "agendas".
Your probably not going to get a very good unbiased answer as these two camps are much like the Emacs vs VIM war.
Answer your questions w/ a Spring bias
Because it in theory buys your less vendor lock-in (albeit I have found this to be the opposite).
Spring's biggest advantage is AspectJ AOP. By far.
I guess see Philippe's answer.
(start of rant)
Since #PhilippeMarschall defended Java EE I will say that I have done the Tomcat+RabbitMQ+Spring route and it works quite well. #PhilippeMarschall discussion is valid if you want proper JTA+JMS but with proper setup with Sprig AMQP and an a good transactional database like Postgresql this is less of an issue. Also he is incorrect about the message queue transactions not being bound/synchronized to the platform transactions as Spring supports this (and IMHO much more elegantly with #Transactional AOP). Also AMQP is just plain superior to JMS.
(end of rant)
We are using JBoss over tomcat for the JNDI data sources and pooling.. It makes it so the programmer don't have to know anything about the database but its JNDI name

Using JNDI for distributed configuration

We're looking at how to do distributed configuration within our primarily Java based deployment. We have a number of applications and it makes sense to centralise the configuration of the applications. JNDI appears to be the standard choice, probably backing off to something like ApacheDS (that way we can store non Java config in there as well). Here are some of the things that I've considered. Has anyone tried something similar? Any recommendations?:
Distributed
This would be for multiple applications on multiple machines, some of the applications would be clustered. The Directory Server should also ideally be clustered.
Lightweight
JNDI has a bit of a J2EE feel to it. Anyone use an alternative distributed configuration mechanism. The applications themselves tend to be relatively lightweight rather than full Java EE applications (ok controversial whether Java EE is still considered heavyweight and requirements are certainly heavyweight).
Supports fallbacks
Often the same configuration applies to multiple applications (e.g. multiple applications may connect to the same database). One the other hand, some applications may need specific configuration. Sometimes it is difficult to know in advance whether an application will use a 'global' configuration or something specific, so being able to first search for application / host specific configuration and then falling back would be good. I'm thinking of a structure something like this:
/global/host/application/instance or /global/application/host/instance:
so, start by checking to see if there is any configuration specific to this instance of the application on this host, then check if there is any configuration specific to this application for this host, then check to see if there is anything specific for this application, then try the global setting. Are there any best practices for this kind of thing?
Live configuration changes
Spring allows configuration with a jee:jndi-lookup and you can choose not to cache the value which means it is looked up each request. I'm not sure that makes sense for "String" type configuration values. It also doesn't appear to use the NamingListener way of detecting changes in the DS. It would be good to be able to update a value on the Directory Server and have that change broadcast to all of the applications that use it.
Other considerations
Managing different environments
Adding the configuration to source control so that it can have change management applied to it
Managing different versions
Rolling back
Have you considered using a database to store the application configuration?
Apache Commons has a DatabaseConfiguration class that exposes your table as a java.util.Properties instance (see http://commons.apache.org/configuration/apidocs/org/apache/commons/configuration/DatabaseConfiguration.html).

What's the best way to share business object instances between Java web apps using JBoss and Spring?

We currently have a web application loading a Spring application context which instantiates a stack of business objects, DAO objects and Hibernate. We would like to share this stack with another web application, to avoid having multiple instances of the same objects.
We have looked into several approaches; exposing the objects using JMX or JNDI, or using EJB3.
The different approaches all have their issues, and we are looking for a lightweight method.
Any suggestions on how to solve this?
Edit: I have received comments requesting me to elaborate a bit, so here goes:
The main problem we want to solve is that we want to have only one instance of Hibernate. This is due to problems with invalidation of Hibernate's 2nd level cache when running several client applications working with the same datasource. Also, the business/DAO/Hibernate stack is growing rather large, so not duplicating it just makes more sense.
First, we tried to look at how the business layer alone could be exposed to other web apps, and Spring offers JMX wrapping at the price of a tiny amount of XML. However, we were unable to bind the JMX entities to the JNDI tree, so we couldn't lookup the objects from the web apps.
Then we tried binding the business layer directly to JNDI. Although Spring didn't offer any method for this, using JNDITemplate to bind them was also trivial. But this led to several new problems: 1) Security manager denies access to RMI classloader, so the client failed once we tried to invoke methods on the JNDI resource. 2) Once the security issues were resolved, JBoss threw IllegalArgumentException: object is not an instance of declaring class. A bit of reading reveals that we need stub implementations for the JNDI resources, but this seems like a lot of hassle (perhaps Spring can help us?)
We haven't looked too much into EJB yet, but after the first two tries I'm wondering if what we're trying to achieve is at all possible.
To sum up what we're trying to achieve: One JBoss instance, several web apps utilizing one stack of business objects on top of DAO layer and Hibernate.
Best regards,
Nils
Are the web applications deployed on the same server?
I can't speak for Spring, but it is straightforward to move your business logic in to the EJB tier using Session Beans.
The application organization is straight forward. The Logic goes in to Session Beans, and these Session Beans are bundled within a single jar as an Java EE artifact with a ejb-jar.xml file (in EJB3, this will likely be practically empty).
Then bundle you Entity classes in to a seperate jar file.
Next, you will build each web app in to their own WAR file.
Finally, all of the jars and the wars are bundled in to a Java EE EAR, with the associated application.xml file (again, this will likely be quite minimal, simply enumerating the jars in the EAR).
This EAR is deployed wholesale to the app server.
Each WAR is effectively independent -- their own sessions, there own context paths, etc. But they share the common EJB back end, so you have only a single 2nd level cache.
You also use local references and calling semantic to talk to the EJBs since they're in the same server. No need for remote calls here.
I think this solves quite well the issue you're having, and its is quite straightforward in Java EE 5 with EJB 3.
Also, you can still use Spring for much of your work, as I understand, but I'm not a Spring person so I can not speak to the details.
What about spring parentContext?
Check out this article:
http://springtips.blogspot.com/2007/06/using-shared-parent-application-context.html
Terracotta might be a good fit here (disclosure: I am a developer for Terracotta). Terracotta transparently clusters Java objects at the JVM level, and integrates with both Spring and Hibernate. It is free and open source.
As you said, the problem of more than one client web app using an L2 cache is keeping those caches in synch. With Terracotta you can cluster a single Hibernate L2 cache. Each client node works with it's copy of that clustered cache, and Terracotta keeps it in synch. This link explains more.
As for your business objects, you can use Terracotta's Spring integration to cluster your beans - each web app can share clustered bean instances, and Terracotta keeps the clustered state in synch transparently.
Actually, if you want a lightweight solution and don't need transactions or clustering just use Spring support for RMI. It allows to expose Spring beans remotely using simple annotations in the latest versions. See http://static.springframework.org/spring/docs/2.0.x/reference/remoting.html.
You should take a look at the Terracotta Reference Web Application - Examinator. It has most of the components you are looking for - it's got Hibernate, JPA, and Spring with a MySQL backend.
It's been pre-tuned to scale up to 16 nodes, 20k concurrent users.
Check it out here: http://reference.terracotta.org/examinator
Thank you for your answers so far. We're still not quite there, but we have tried a few things now and see things more clearly. Here's a short update:
The solution which appears to be the most viable is EJB. However, this will require some amount of changes in our code, so we're not going to fully implement that solution right now. I'm almost surprised that we haven't been able to find some Spring feature to help us out here.
We have also tried the JNDI route, which ends with the need for stubs for all shared interfaces. This feels like a lot of hassle, considering that everything is on the same server anyway.
Yesterday, we had a small break through with JMX. Although JMX is definately not meant for this kind of use, we have proven that it can be done - with no code changes and a minimal amount of XML (a big Thank You to Spring for MBeanExporter and MBeanProxyFactoryBean). The major drawbacks to this method are performance and the fact that our domain classes must be shared through JBoss' server/lib folder. I.e., we have to remove some dependencies from our WARs and move them to server/lib, else we get ClassCastException when the business layer returns objects from our own domain model. I fully understand why this happens, but it is not ideal for what we're trying to achieve.
I thought it was time for a little update, because what appears to be the best solution will take some time to implement. I'll post our findings here once we've done that job.
Spring does have an integration point that might be of interest to you: EJB 3 injection nterceptor. This enables you to access spring beans from EJBs.
I'm not really sure what you are trying to solve; at the end of the day each jvm will either have replicated instances of the objects, or stubs representing objects existing on another (logical) server.
You could, setup a third 'business logic' server that has a remote api which your two web apps could call. The typical solution is to use EJB, but I think spring has remoting options built into its stack.
The other option is to use some form of shared cache architecture... which will synchronize object changes between the servers, but you still have two sets of instances.
Take a look at JBossCache. It allows you to easily share/replicate maps of data between mulitple JVM instances (same box or different). It is easy to use and has lots of wire level protocol options (TCP, UDP Multicast, etc.).

Categories

Resources