I've learned a lot about JMX over the past couple of years and have built some pretty fancy MBeans for my web applications. However, I'm not sure I have a good answer to a pretty basic question:
Why use JMX over simple HTTP servlets?
My current web applications offer redundant monitoring options: I can access the data that needs to be monitored via JMX with a client like JConsole or I can access that same data in XML format via a servlet. I don't see a strong reason to use one method over another, but the servlet method does have the major advantage of being readable by a simple http client / web browser.
I can see how JMX would be quite useful for Java applications that aren't web apps, but I can't see any advantage to using JMX for a web app.
Why use JMX over simple HTTP servlets?
From my standpoint, JMX is better for 3 reasons:
It requires less code to enable monitoring points.
It deals with Java serialized objects end-to-end so there is better data consistency.
It works with programs that are not servlet based (as you mentioned).
JMX offers a much easier interface to specific data items. You can certainly write the same functionality in a number of servlets, but it is easier for me to expose those using JMX.
For example, if you are using Spring then you can use the org.springframework.jmx.export annotations (#ManagedResource, #ManagedAttribute, etc.) to mark up your classes. I've also published my SimpleJmx framework so you can easily expose attributes and operations with just a couple annotations independent of Spring. For example:
#JmxResource(domainName = "j256", objectName = "lookupCache")
public class LookupCache {
// this can also be done as #JmxAttributeMethod on the getter/setters
#JmxAttributeField(description = "Number of hits in the cache")
private int hitCount;
...
#JmxOperation(description = "Flush the cache")
public void flushCache() {
...
}
}
I have a fully working example program to see how it works. So all you need to do to expose a value or operation is add an annotation to the class and each attribute and/or method. The code to publish it using SimpleJmx looks like the following. Spring is similar albeit with beans:
// create a new server listening on port 8000
JmxServer jmxServer = new JmxServer(8000);
jmxServer.start();
// register our lookupCache object defined above
jmxServer.register(lookupCache);
To get similar functionality in servlets would take a lot more code than just annotations. That said, there may exist frameworks which provide similar functionality in servlet land that I don't know about.
Some more notes:
There are probably better monitoring tools that grok HTTP/HTML but there are also a ton of distributed JMX monitoring applications. Probably a toss up.
Being able to programmatically get objects from JMX servers is a plus as opposed to just strings from a servlet page. SimpleJmx also supports a simple JMX client although better ones exist out there.
Obviously a lot of other worthwhile data is already published by the JVM by default: VM settings, thread details, memory information, etc..
In addition to reading values, JMX can be used to invoke methods on Management Beans.
For example, we often use it to force a JVM garbage collection for Tomcat instances remotely.
Also because JMX is a different port that http/https you can limit access at the network level via firewalls. JMX has built-in username/password authentication as well.
A web servlet would have to implement it's own access control.
In my opinion JMX is overrated and it can be tricky to configure.
If your application is already a webcontainer I think you should definitely go for a simple servlet.
A tiny servlet approach like nudge4j would give you everything and more.
Related
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
I'm creating an application that relies heavily on dynamic creation/management of various resources like jms queues, webservice endpoints, jdbc connections... I have a background in java EE and am currently working on a jboss 7 server however I'm finding it increasingly difficult to control these things programmatically. The hardest thing to control seem to be the webservices. I need to be able to generate WSDLs (and XSDs) on the fly, manage the endpoints, soap handlers etc and the system simply does not seem to be set up to do that.
Other application servers don't seem to really offer any groundbreaking solutions so I'm wondering whether perhaps java EE is not the best solution to this particular problem?
Is there an application server that allows you to do just that? Is there another technology that does? Should I just roll a custom solution that integrates all the separate modules (e.g. a jms server, a web server etc...)?
UPDATE
To clarify, most java EE stuff is accomplished through a mixture of annotations and XML configuration. This however assumes that you have a POJO and/or a jar/war/... per resource.
Suppose I have a #WebServiceProvider bean which can be reused for multiple input/output combinations (for example because it dynamically redirects the content). I need to be able to deploy a new "instance" of the provider on the fly. This means I do not want to duplicate the code and redeploy it, I just want to take that one existing bean on the classpath and deploy it multiple times with different configuration settings. This also means I need to manage the WSDL dynamically. The end result should be a webservice that works pretty much like a standard webservice on the application server with the necessary integrated security, soap handlers,...
I imagine that at some point in the application server code, there must be a class "WebserviceManager" which has a method like "createWebservice(...)" that is actually used by the deployment module whenever it discovers a webservice annotation. I want access to that method and similar methods for creating jdbc connections, jms queues,...
You can use OSGi for these kind of scenarios. It is perfect for hot deployment of varios modules.
I have a web application running on Google App Engine (GAE) for JAVA. I'm authenticating the client at the Servlet layer but would like to make the client information available to my business and data layers without having to pass the client object through the arguments of every single function.
I'm considering setting up a "session" type object using ThreadLocal. That way any function can just say something like:
CurrentUser.getRoles();
Is this a good way to do this or is there something else that is a more accepted solution?
Thanks!
This will probably work and will be utterly convenient, but usually I try to avoid ThreadLocals for similar use cases as much as I can. Reasons:
You code just suddenly starts to depend on the fact that underlying container uses different threads for different users. If the container will start using NIO, different type of threads (e.g. green threads which would not be mapped into java.lang.Thread on some exotic JVM), etc. you will be out of luck.
ThreadLocals tend to be forgotten to be cleaned up after using them. So if your server will spike in usage and one of the users will put lots of stuff into 'cache', you might run out of RAM.
As a consequence of not cleaning up after a request, ThreadLocal can expose security vulnerability assuming the other user would jump unto the same thread.
Finally, I believe ThreadLocals were designed for environments where you have an absolute control over threads in your context, and this use case is just so far beyond.
Unfortunately I don't know much about GAE to suggest a viable alternative, sorry about that!
ThreadLocals are a completely accepted way to store such information. Besides us I also know from Alfresco that they do it.
If using Spring and Spring Security works for you then you can use the code I've built as part of jappstart for your authentication/authorization. This information is then available via Spring Security.
Currently, I only know a way of doing RPC for POJOs in Java, and is with the very complex EJB/JBoss solution.
Is there any better way of providing a similar functionality with a thiner layer (within or without a Java EE container), using RMI or something that can serialize and send full blown objects over the wire?
I'm not currently interested in HTTP/JSON serialization BTW.
EDIT: For clarification: I'm trying to replace an old EJB 2.1/JBoss 4 solution with something more easy to manage at the container level. I need to have entire control over the database(planning to use iBATIS which would allow me to use fairly complex SQL very easily), but the only things I want to keep over the wire are:
Invocation of lookup/data modification methods (automagic serialization goes here).
Transparent session control (authentication/authorization). I still have to see how to accomplish this.
Both items have to work as a whole, of course. No access should be granted to users without credentials.
Because I'm not very fond of writing webapps, I plan to build a GUI (Swing or SWT) that would only manage POJOs, do some reporting and invoke methods from the container. I want the serialization to be as easy as possible.
As is nearly always the case, Spring comes to the rescue. From the reference documentation, you will want to read Chapter 17. Remoting and web services using Spring.
There are several methods to choose from. The beauty of Spring is that all your interfaces and implementations are vanilla POJOs. The wiring into RMI or whatever is handled by Spring. You can:
Export services using RMI:
probably the simplest approach;
Use HTTP invoker: if remote access is an issue, this might be better for firewalls, etc than pure RMI; or
Use Web Services, in which case I would favour JAX-WS over JAX-RPC.
Spring has the additional benefit in that it can do the wiring for both the server and the client, easily and transparently.
Personally I would choose either (2) or (3). HTTP is network friendly. It's easy to deploy in a Web container. Jetty's long-lived connections give you the option over server push (effectively) over HTTP.
All of these methods allow complex objects to be sent across the wire but they are subtly different in this regard. You need to consider if your server and client are going to be distributed separately and whether it's an issue if you change the interface that you need to redistribute the class files. Or you can use a customized serialization solution (even XML) to avoid this. But that has issues as well.
Using a Web container will allow you to easily plug-in Spring Security, which can be a bit daunting at first just because there are so many options. Also, HttpSession can be used to provide state information between requests.
Simple RPC is exactly what RMI was built for. If you make a serializable interface, you can call methods on one app from another app.
If you only need value objects then just ensure the POJOs implement Serializable and write the objects across sockets (using ObjectOutputStream). On the receiving end read the objects using ObjectInputStream. The receiving end has to have a compatible version of the POJO (see serialVersionUID).
Hessian/Burlap 'protocol-ize this: http://hessian.caucho.com/ and http://www.caucho.com/resin-3.0/protocols/burlap.xtp
You could try XStream (http://x-stream.github.io/) over REST. Easy to apply on e pre-existing set of pojos.
Can you give some further information as to what you're trying to achieve, since you're not interested in rest/json ?
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.).