| JBoss MBeans POJO |
|
|
|
| Written by Mark S. | |||||||||||||||||||||||||||||
| Monday, 25 August 2008 19:32 | |||||||||||||||||||||||||||||
|
JMX MBean services are the core building blocks of the JBoss Application Server. The success of the full Open Source J2EE stack lies with the use of Java Management Extension which provides a common spine that allows the user to integrate modules, containers, and plug-ins. While MBean services are very useful, developing them is not trivial. In a regular JMX server environment, you need to extend numerous framework classes and work with reflection-like APIs. Moreover common IDE have showed a greater attention for other JEE components like EJB which can bedeveloped using simple wizards.
Until now! In the JBoss EJB 3.0 server, you can use simple annotations to configure POJOs and make them available as MBean services. In other words no mess with invasive frameworks, no configuration files: just a couple of annotations and you have your EJB 3.0's style MBean services. Not only ! Developers can specify dependency between MBean services so that they are started in a particular order when the server starts, which makes them especially suitable for implementing the server's internal infrastructure services. A lot of JBoss internal services are implemented as MBeans. They communicate with each other via the internal JMX bus (i.e., the JBoss JMX Microkernel). So how are my MBeans different from EJB services ?
Let's see our first sample.
package sample.jmx;
import org.jboss.annotation.ejb.Service;
import org.jboss.annotation.ejb.Management;
@Service (objectName="sampleJMX:service=calculateInterest")
@Management(CalculateInterest.class)
public class CalculateInterestMBean implements CalculateInterest {
double interestRate;
public void setInterestRate (double interestRate) {
this.interestRate = interestRate;
}
public double getInterestRate () {
return interestRate;
}
public double calculate (double saving, int days) {
double interest = (saving * days * this.interestRate)/36500;
return interest;
}
// Lifecycle methods
public void create() throws Exception {
this.interestRate = 5;
System.out.println("CalculateInterestMBean - Creating");
}
public void destroy() {
System.out.println("CalculateInterestMBean - Destroying");
}
}
Just a plain POJO with @Service annotation: this defines CalculatorInterestMBean as a singleton service in JBoss. It defines the objectName for this MBean as "sampleJMX:service=calculateInterest".
The second annotation is @Management. When JBoss finds this annotation will inspect this interface, and create and install an MBean implementing the attributes and operations defined in the @Management interface. And here's the implemented interface : no annotations are needed here.
package sample.jmx;
public interface CalculateInterest {
public void setInterestRate (double interestRate);
public double getInterestRate ();
// The management method
public double calculate (double saving, int days);
// Life cycle method
public void create () throws Exception;
public void destroy () throws Exception;
}
Lifecycle methodsJust as for "normal" MBeans in JBoss, Service POJOs support lifecycle management, but you don't need to create all these methods. You can pick and choose only those needed by your Service. If present in the service, the container will call these methods as follows: create() - called by the server when the service is created and all the services it depends upon have been created too. At this point the service (and all the services it depends on) is installed in the JMX server, but is not yet fully functional. start() - called by the server when the service is started and all the services it depends upon have been started too. At this point the service (and all the services it depends on) is fully functional. stop() - called by the server when the service is stopped. At this point the service (and all the services that depend on it) is no longer fully operational. destroy() - called by the server when the service is destroyed and removed from the MBean server. At this point all the MBeans that depend on the Packaging and deployingPackaging your Service is just a matter of compiling the classes and putting them in a jar file (You can even choose to deploy them as exploder jar folder which is easier for development use) If you're using an Eclipse based tool simply add to your Project--->Properties--->Java Build Path the library jboss-annotations-ejb3.jar which is found in your JBOSS_HOME/client folder. If you're compiling with the console just throw a javac -classpath c:\jboss-4.2.0.GA\client\jboss-annotations-ejb3.jar;. -d . *.java (Change the JBoss location to your JBoss Home). Now jar everything: jar cvf Calculate.jar sample and copy the Calculate.jar in the "deploy" directory of JBoss. If everything was done correctly you should see in the server logs... 11:03:02,546 INFO [JmxKernelAbstraction] installing MBean: jboss.j2ee:jar=Calculate.jar,name=CalculateInterestMBean,service=EJB3 with dependencies:
11:03:02,593 INFO [EJBContainer] STARTED EJB: sample.jmx.CalculateInterestMBean ejbName: CalculateInterestMBean 11:03:02,609 INFO [STDOUT] CalculateInterestMBean - Creating 11:03:02,625 INFO [JmxKernelAbstraction]creating wrapper delegate for: org.jboss.ejb3.service.ServiceContainer 11:03:02,625 INFO [JmxKernelAbstraction] installing MBean: jboss.j2ee:jar=Calculate.jar,name=FinancialAdvisorMBean,service=EJB3 with dependencies: 11:03:02,625 INFO [JmxKernelAbstraction] sampleJMX:service=calculateInterest 11:03:02,687 INFO [EJBContainer] STARTED EJB: sample.jmx.FinancialAdvisorMBean ejbName: FinancialAdvisorMBean 11:03:02,703 INFO [STDOUT] FinancialAdvisorMBean - Creating 11:03:02,718 INFO [EJB3Deployer] Deployed: file:/C:/jboss-4.2.0.GA/server/default/deploy/Calculate.jar/ A minimal client For the purpose of testing our MBean we'll write a simple JSP Client which will request to our Service the Calculation of an interest rate:
<%@ page import="javax.management.*,sample.jmx.*,org.jboss.mx.util.*" %>
<% CalculateInterest cal = null;
try {
MBeanServer server = MBeanServerLocator.locate();
cal = (CalculateInterest) MBeanProxyExt.create(
CalculateInterest.class,
"sampleJMX:service=calculateInterest",
server);
cal.setInterestRate(7.5);
out.println("Amount of Interests: " +cal.calculate(10000, 180));
} catch (Exception e) {
e.printStackTrace ();
}
%>
This will produce as output:
Amount of Interests: 369.86301369863014
Advanced Service POJOS conceptsIn the previous chapters we have learnt how to develop JMX MBean services using simple EJB 3.0 style annotations. In this trail we'll see how services can collaborate with other services, in other words we'll define the dependencies between services. Imagine our Interest Calculator application is part of a larger Service, for example The dependancy of a Service on another Service can be coded with a simple annotation: @Service (objectName="sampleJMX:service=financialAdvisor")
@Depends ({"sampleJMX:service=calculateInterest", "sampleJMX:service=calculateLoan"}) Depends injection One particular type of dependancy is the "Dependancy Injection". With this Instead of annotating the dependancy at Class level the dependencies are specified on fields and setter methods. @Depends ("sampleJMX:service=calculateInterest")
So let's see a complete example of a Service which is dependant on another:
package sample.jmx;
import org.jboss.annotation.ejb.Depends;
import org.jboss.annotation.ejb.Service;
import org.jboss.annotation.ejb.Management;
@Service(objectName = "sampleJMX:service=financialAdvisor")
@Management(FinancialAdvisor.class)
public class FinancialAdvisorMBean implements FinancialAdvisor {
private CalculateInterest calculateService;
public String getAdvice() {
if (calculateService.getInterestRate() < 5) {
return "Today you invest with low interest rate";
} else if (calculateService.getInterestRate() == 5) {
return "Today you invest with ordinary interest rate";
} else {
return "Today you invest with high interest rate";
}
}
public CalculateInterest getCalculateInterest() {
return calculateService;
}
@Depends("sampleJMX:service=calculateInterest")
public void setCalculateInterest(CalculateInterest calculateService) {
this.calculateService = calculateService;
}
public void create() throws Exception {
System.out.println("FinancialAdvisorMBean - Creating");
}
public void destroy() {
System.out.println("FinancialAdvisorMBean - Destroying");
}
}
javac -classpath c:\jboss-4.2.0.GA\client\jboss-annotations-ejb3.jar;. -d . *.java now jar everything and deploy : 11:03:02,546 INFO [JmxKernelAbstraction] installing MBean: jboss.j2ee:jar=Calculate.jar,name=CalculateInterestMBean,service=EJB3 with dependencies:
11:03:02,593 INFO [EJBContainer] STARTED EJB: sample.jmx.CalculateInterestMBean ejbName: CalculateInterestMBean 11:03:02,609 INFO [STDOUT] CalculateInterestMBean - Creating 11:03:02,625 INFO [JmxKernelAbstraction] creating wrapper delegate for: org.jboss.ejb3.service.ServiceContainer 11:03:02,625 INFO [JmxKernelAbstraction] installing MBean: jboss.j2ee:jar=Calculate.jar,name=FinancialAdvisorMBean,service=EJB3 with dependencies: 11:03:02,625 INFO [JmxKernelAbstraction] sampleJMX:service=calculateInterest 11:03:02,687 INFO [EJBContainer] STARTED EJB: sample.jmx.FinancialAdvisorMBean ejbName: FinancialAdvisorMBean 11:03:02,703 INFO [STDOUT] FinancialAdvisorMBean - Creating 11:03:02,718 INFO [EJB3Deployer] Deployed: file:/C:/jboss-4.2.0.GA/server/default/deploy/Calculate.jar/ This simple application will yield a financial advice depending on the interest rate (which is set by CalculateInterestMBean) InterceptorsYou can define interceptors for your service beans in the same way as shown in EJB3 Interceptors. This example defines one in the ServiceThree bean class itself. @AroundInvoke
SummaryIn this trail, you learned how to develop JMX MBean services using simple EJB 3.0 style annotations. MBean services are very useful when you need to provide manageable services to other components or services inside the JBoss application server.
JBoss.org Search
Custom Search
Only registered users can write comments!
Powered by !JoomlaComment 3.26
3.26 Copyright (C) 2008 Compojoom.com / Copyright (C) 2007 Alain Georgette / Copyright (C) 2006 Frantisek Hliva. All rights reserved." |
|||||||||||||||||||||||||||||
| Last Updated on Tuesday, 28 October 2008 10:31 | |||||||||||||||||||||||||||||






The way you define them is very similar to how you define stateless or stateful session beans. One very important difference is that there will only ever be ONE instance of the service bean. i.e. it is not pooled - the bean instance is a singleton. The singleton bean contains shared state, so data set by one client is accessible by other clients.
The @Depends annotation specifies that this service depends on the service created for calculateInterest. i.e. it cannot be started until the service created for calculateInterest has been started.
The call to ctx.proceed() causes the next object in the chain of interceptors to get invoked. At the end of the chain of interceptors, the actual bean method gets called.