Can an MBean be run under Tomcat? - java

We have 2 applications that run under JBoss. I am looking for a way to reduce the overhead of the server. The main app runs under Tomcat. The other app is made up of MBeans. Is there a way to run MBeans under Tomcat?
Alternative suggestions are appreciated.

MBeans are a part of the JMX specification which is included in the JRE. It should be possible to run MBeans under Tomcat. Tomcat 5 or later provides an MBean server.

You can use the following JVM arguments to startup Tomcat with MBean enabled
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=4444 (could be anything)
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false

You also should use the MBean server that is in tomcat - you have to find that one via:
// find the existing MBean server (tomcat's) in lieu of
// creating our own
//
ArrayList<MBeanServer> mbservers = MBeanServerFactory
.findMBeanServer(null);
int nservers = mbservers.size();
if (nservers > 0) {
//
// TODO: A better way to get the currently active server ?
// For some reason, every time the webapp is reloaded there is one
// more instance of the MBeanServer
mbserver = (MBeanServer) mbservers.get(nservers - 1);
}
if (mbserver == null) {
mbserver = MBeanServerFactory.createMBeanServer();
}

Try this http://community.jboss.org/wiki/JBossASTuningSliming. Sure you have many services without usage.

Related

How to start and stop Tomcat cleanly from Java and why my way doesn't work repeatably?

I am writing a Quartz application that runs on Windows and calls Lucene and Solr to run indexing jobs. It runs a sequence of jobs, and each job consists of these steps:
Make sure Tomcat is stopped (Solr running under Tomcat prevents index dir from being deleted or copied)
Delete old index directory if necessary
Start Tomcat
Make sure Tomcat and Solr app are running
Run the indexing job
Stop Tomcat
Make sure Tomcat is stopped
Copy index directory to an archive
I decided to have the code that starts and stops Tomcat set the system properties that are set in Startup.bat, Shutdown.bat and Catalina.bat, and just call Bootstrap.main with "start" and "stop" parameters. This worked for one iteration, but not when I tried a Quartz run in which I set up two iterations.
When my code shut down Tomcat at the end of the first iteration, all of the usual messages were displayed, including
INFO: Stopping ProtocolHandler ["http-bio-5918"]
(I am using port 5918) but when it tried to start Tomcat at the beginning of the second iteration, it got thes errors:
SEVERE: Failed to initialize end point associated with ProtocolHandler ["http-bio-5918"]
java.net.BindException: Address already in use: JVM_Bind <null>:5918
and
SEVERE: Failed to initialize connector [Connector[HTTP/1.1-5918]]
org.apache.catalina.LifecycleException: Failed to initialize component [Connector[HTTP/1.1-5918]]
I ran netstat -an in a command prompt window, and it confirmed that port 5918 was in use. There's nothing special about the code I am using to check if Tomcat is running. I've seen in various places on the internet.
public boolean isTomcatRunning(String url) {
boolean isRunning = false;
try {
new URL(url).openConnection().connect();
isRunning = true;
} catch (IOException e) {
isRunning = false;
}
return isRunning;
}
but it apparently tells me that Tomcat is not running when it is.
As I said, I am starting and stopping Tomcat by calling Bootstrap.main(new String[]{"start"}) and Bootstrap.main(new String[]{"stop"}). The only thing peculiar about that is that is that when I simply call Bootstrap.main(new String[]{"start"}), it doesn't seem to return (I haven't waited long enough yet to see if it is hanging or just taking a long time), so I have been running it inside a thread.
Maybe that is causing the problem, as it looks like Catalina.bat isn't doing anything special and it returns from startup just fine. I wonder if there is an additional setup I need to do to enable it to run startup in the main thread without hanging.
In any case, this is what I am puzzled about with starting and stopping Tomcat from within my Quartz application, and I would appreciate any help and suggestions you can offer.
I strongly suggest that you wrap your Tomcat instance with a wrapper that controls the lifecycle of your Tomcat instance. Such wrapper is the Java Service Wrapper. An older version (3.2.3 I believe) is "free" and works fine with newer Tomcat instances.
Your controlling application then "talks" to the wrapper to start/stop the Tomcat application. There are multiple benefits with this approach. One of them is that you are not subject to your Tomcat application hanging and the port you are testing not replying anymore.

Java RMI - Remote Deployment

I have a locally working JAVA RMI Applicaton(Server & Client).
I have used Eclipse & a plugin(Genady) to write & run these applications.
There are three parts in my project:
1. Server
2. Interface(Common for both client & server)
3. Client
Local deployment, using Eclipse(+plugin), works perfectly. The client uses the common interface(added to the "Build Path") to communicate(to n fro) with the server(which also has the common interface added to its Build Path in eclipse).
And now, I'm planning to test the same system in two different computers, both having Internet connection.
What do I do now?
Should I be installing Apache on one computer(Server) & put the Server+Interface files(class-files) into the web-accessible directory? & then run the Client-files(having both client & interface class files) from another computer(Client)??
Can someone help me configure this? I mean, a step-by-step guide as to what I should be doing in order for the remote deployment to work?
Is using Apache(or any web server application) compulsory?? Any other alternative for my application to work without using a web server(I mean, like direct connection or something?)?
(I feel I've given all the info that is required. But if any more info is needed, please ask.)
This is my final year project & my final demo is coming up soon!
Thank you, in advance!
I don't know what Genady does since I rarely use Eclipse.
Developing RMI applications is very easy anyway.
Pack the server code and run it on the remote machine (the R in RMI)(a.k.a. server host), it should register itself with the Registry which by default uses port 1099 but you can create a registry in any port you like:
MyRemoteInterface stub = (MyRemoteInterface) UnicastRemoteObject.exportObject(server, 0); //I don't know if this is needed anymore, or you could make the "server" extend UnicastRemoteObject
int thePortUsedInTheServer = 1099; //default
Registry registry = Registry.createRegistry(thePortUsedInTheServer);
registry.rebind("Server", stub));
Pack the client code and run it on the client(s) (the M+I in RMI), it should locate the Registry in the remote machine (host+port):
String host = ...; //the host where the server is
int port = ...; //the port used in the server
Registry registry = LocateRegistry.getRegistry(host, port);
MyRemoteInterface stub = (MyRemoteInterface)registry.lookup("Server");
stub.myRemoteMethod(); //call your remote methods
The javadoc should help you out. Nothing else is required, no Apache, etc. Watch out for aggresive anti-virus software, firewalls, and the like. Those are the only real issues after you get the gist of it.

How can I monitor/log Tomcat's thread pool?

I have a Tomcat installation where I suspect the thread pool may be decreasing over time due to threads not being properly released. I get an error in catalina.out when maxthreads is reached, but I would like to log the number of threads in use to a file every five minutes so I can verify this hypothesis. Would anyone please be able to advise how this can be be done?
Also in this installation there is no Tomcat manager, it appears whoever did the original installation deleted the manager webapp for some reason. I'm not sure if manager would be able to do the above or if I can reinstall it without damaging the existing installation? All I really want to do is keep track of the thread pool.
Also, I noticed that maxthreads for Tomcat is 200, but the max number of concurrent connections for Apache is lower (Apache is using mod_proxy and mod_proxy_ajp (AJP 1.3) to feed Tomcat). That seems wrong too, what is the correct relationship between these numbers?
Any help much appreciated :D
Update: Just a quick update to say the direct JMX access worked. However I also had to set Dcom.sun.management.jmxremote.host. I set it to localhost and it worked, however without it no dice. If anyone else has a similar problem trying to enable JMX I recommend you set this value also, even if you are connecting from the local machine. Seems it is required with some versions of Tomcat.
Just a quick update to say the direct JMX access worked. However I also had to set Dcom.sun.management.jmxremote.host. I set it to localhost and it worked, however without it no dice. If anyone else has a similar problem trying to enable JMX I recommend you set this value also, even if you are connecting from the local machine. Seems it is required with some versions of Tomcat.
Direct JMX access
Try adding this to catalina.sh/bat:
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=5005
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
UPDATE: Alex P suggest that the following settings might also be required in some situations:
-Dcom.sun.management.jmxremote.host=localhost
This enables remote anonymous JMX connections on port 5005. You may also consider JVisualVM which is much more please and allows to browse JMX via plugin.
What you are looking for is Catalina -> ThreadPool -> http-bio-8080 -> various interesting metrics.
JMX proxy servlet
Easier method might be to use Tomcat's JMX proxy servlet under: http://localhost:8080/manager/jmxproxy. For instance try this query:
$ curl --user tomcat:tomcat http://localhost:8080/manager/jmxproxy?qry=Catalina:name=%22http-bio-8080%22,type=ThreadPool
A little bit of grepping and scripting and you can easily and remotely monitor your application. Note that tomcat:tomcat is the username/password of user having manager-jmx role in conf/tomcat-users.xml.
You can deploy jolokia.war and then retrieve mbeans values in JSON (without the manager):
http://localhost:8080/jolokia/read/Catalina:name=*,type=ThreadPool?ignoreErrors=true
If you want only some values (currentThreadsBusy, maxThreads, currentThreadCount, connectionCount):
http://localhost:8080/jolokia/read/Catalina:name=*,type=ThreadPool/currentThreadsBusy,maxThreads,currentThreadCount,connectionCount?ignoreErrors=true
{
request: {
mbean: "Catalina:name="http-nio-8080",type=ThreadPool",
attribute: [
"currentThreadsBusy",
"maxThreads",
"currentThreadCount",
"connectionCount"
],
type: "read"
},
value: {
currentThreadsBusy: 1,
connectionCount: 4,
currentThreadCount: 10,
maxThreads: 200
},
timestamp: 1490396960,
status: 200
}
Note: This example works on Tomcat7 +.
For a more enterprise solution. I have been using New Relic in our production environment.
This provides a graph of the changes to the threadpool over time.
There are cheaper tools out meanwhile: I am using this jar here: https://docs.cyclopsgroup.org/jmxterm
You can automate it via shell/batch scripts. I regexed the output and let prometheus poll it for displaying it in grafana.

How can I make "jconsole" work with Websphere 6.1?

I've deployed some Managed Beans on WebSphere 6.1 and I've managed to invoke them through a standalone client, but when I try to use the application "jconsole" distributed with the standard JDK can can't make it works.
Has anyone achieved to connect the jconsole with WAS 6.1?
IBM WebSphere 6.1 it's supossed to support JSR 160 JavaTM Management Extensions (JMX) Remote API. Furthermore, it uses the MX4J implementation (http://mx4j.sourceforge.net). But I can't make it works with neither "jconsole" nor "MC4J".
I have the Classpath and the JAVA_HOME correctly setted, so the issue it's not there.
WebSphere's support for JMX is crap. Particularly, if you need to connect to any secured JMX beans. Here's an interesting tidbit, their own implementation of jConsole will not connect to their own JVM. I have had a PMR open with IBM for over a year to fix this issue, and have gotten nothing but the runaround. They clearly don't want to fix this issue.
The only way I have been able to invoke remote secured JMX beans hosted on WebSphere has been to implement a client using the "WebSphere application client". This is basically a stripped down app server used for stuff like this.
Open a PMR with IBM. Perhaps if more people report this issue, they will actually fix it.
Update: You can run your application as a WebSphere Application Client in RAD. Open the run menu, then choose "Run...". In the dialog that opens, towards the bottom on the left hand side, you will see "WebSphere v6.1 Application Client". I'm not sure how to start and Application Client outside of RAD.
IT WORKS !
http://issues.apache.org/jira/browse/GERONIMO-4534;jsessionid=FB20DD5973F01DD2D470FB9A1B45D209?page=com.atlassian.jira.plugin.system.issuetabpanels%3Aall-tabpanel
1) Change the config.xml and start the server.
-see here how to change config.xml: http://publib.boulder.ibm.com/wasce/V2.1.0/en/working-with-jconsole.html
2) start the jconsole with : jconsole -J-Djavax.net.ssl.keyStore=%GERONIMO_HOME%\var\security\keystores\geronimo-default -J-Djavax.net.ssl.keyStorePassword=secret -J-Djavax.net.ssl.trustStore=%GERONIMO_HOME%\var\security\keystores\geronimo-default -J-Djavax.net.ssl.trustStorePassword=secret -J-Djava.class.path=%JAVA_HOME%\lib\jconsole.jar;%JAVA_HOME%\lib\tools.jar;%GERONIMO_HOME%\repository\org\apache\geronimo\framework\geronimo-kernel\2.1.4\geronimo-kernel-2.1.4.jar
[or your version of geronimo-kernel jar]
3) in the jconsole interface->advanced, input:
JMX URL: service:jmx:rmi:///jndi/rmi://localhost:1099/JMXSecureConnector
user name: system
password: manager
4) click the connect button.
If you want the WebSphere MBeans this one works for me:
The key is to configure the classpath and the security properly.
in one line:
jconsole -J-Dwas.install.root=C:/was61 -J-Djava.ext.dirs=C:/was61/plugins;C:/was61/plugins/com.ibm.ws.security.crypto_6.1.0;C:/was61/lib;C:/was61/java/jre/lib/ext -J-Dcom.ibm.SSL.ConfigURL="file:../../properties/ssl.client.props" -J-Dcom.ibm.CORBA.ConfigURL="file:../../properties/sas.client.props" service:jmx:iiop://host:port/jndi/JMXConnector
where port = bootstrap port ex: (2809)
Be careful when setting the sas and the ssl props.
Robert
I have successfully connected to ActiveMQ and ServiceMix using the JConsole. Does WAS 6.1 use Java Management Extension (JMX) technology? JMX is required for JConsole.
If your path is set correctly it should work fine. On windows you go to System Properties -> Advanced Tab -> Environment Variables. Have your JAVA_HOME System variable set to the path of your JDK or JRE and your Path variable with %JAVA_HOME%/bin added somewhere in there. Then all you need to do is go to Start->Run->JConsole. Select the correct Process Name and your done.
Where are you having problems at? I hope this helps.
Edit:
Here is the Java Doc's on JConsole.
Hmm... I know that WebSphere is kind of hard to configure. Thats part of the reason we used ServiceMix for our ESB. Maybe its not enabled by default in WebSphere and you would have to turn it on in the config somewhere.
Websphere 6.1 does not support the JConsole for some reason even though it fully implements the JMS specs. Seems to be a week area at the moment. Your best bet is to look at the Admin client to implement you own console.
You all seem to be incorrect. I am running Websphere 6.1.041 , using JDK 1.5 , and I just started up Jconsole and used the "simple connect" tab to connect to localhost with port=0 and without a username and password and it works fine.

NPE in JBossWS on JBoss 4.2.2 with jmxremote enabled

I am trying to set up JBoss 4.2.2 and JConsole for remote monitoring. As per many of the how-to's I have found on the web to do this you need to enable jmxremote by setting the following options in run.conf. (I realize the other two opts disable authentication)
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.port=11099"
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.authenticate=false"
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.ssl=false"
Which results in the following exception:
13:06:56,418 INFO [TomcatDeployer] performDeployInternal :: deploy, ctxPath=/services, warUrl=.../tmp/deploy/tmp34585xxxxxxxxx.ear-contents/mDate-Services-exp.war/
13:06:57,706 WARN [AbstractServerConfig] getWebServicePort :: Unable to calculate 'WebServicePort', using default '8080'
13:06:57,711 WARN [AbstractServerConfig] getWebServicePort :: Unable to calculate 'WebServicePort', using default '8080'
13:06:58,070 WARN [AbstractServerConfig] getWebServicePort :: Unable to calculate 'WebServicePort', using default '8080'
13:06:58,071 WARN [AbstractServerConfig] getWebServicePort :: Unable to calculate 'WebServicePort', using default '8080'
13:06:58,138 ERROR [MainDeployer] start :: Could not start deployment: file:/opt/jboss-4.2.2.GA/server/default/tmp/deploy/tmp34585xxxxxxxxx.ear-contents/xxxxx-Services.war
java.lang.NullPointerException
at org.jboss.wsf.stack.jbws.WSDLFilePublisher.getPublishLocation(WSDLFilePublisher.java:303)
at org.jboss.wsf.stack.jbws.WSDLFilePublisher.publishWsdlFiles(WSDLFilePublisher.java:103)
at org.jboss.wsf.stack.jbws.PublishContractDeploymentAspect.create(PublishContractDeploymentAspect.java:52)
at org.jboss.wsf.framework.deployment.DeploymentAspectManagerImpl.deploy(DeploymentAspectManagerImpl.java:115)
at org.jboss.wsf.container.jboss42.ArchiveDeployerHook.deploy(ArchiveDeployerHook.java:97)
...
My application uses JWS which according to this bug:
https://jira.jboss.org/jira/browse/JBWS-1943
Suggests this workaround:
JAVA_OPTS="$JAVA_OPTS -Djavax.management.builder.initial=org.jboss.system.server.jmx.MBeanServerBuilderImpl"
JAVA_OPTS="$JAVA_OPTS -Djboss.platform.mbeanserver"
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote"
(https://developer.jboss.org/wiki/JBossWS-FAQ#jive_content_id_How_to_use_JDK_JMX_JConsole_with_JBossWS)
I've tried that however that then throws the following exception while trying to deploy a sar file in my ear which only contains on class which implements Schedulable for a couple of scheduled jobs my application requires:
Caused by: java.lang.NullPointerException
at EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap.hash(ConcurrentReaderHashMap.java:298)
at EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap.get(ConcurrentReaderHashMap.java:410)
at org.jboss.mx.server.registry.BasicMBeanRegistry.getMBeanMap(BasicMBeanRegistry.java:959)
at org.jboss.mx.server.registry.BasicMBeanRegistry.contains(BasicMBeanRegistry.java:577)
Any suggestions on where to go from here?
EDIT:
I have also tried the following variation:
JAVA_OPTS="$JAVA_OPTS -DmbipropertyFile=../server/default/conf/mbi.properties -DpropertyFile=../server/default/conf/mdate.properties -Dwicket.configuration=DEVELOPMENT"
JAVA_OPTS="$JAVA_OPTS -Djavax.management.builder.initial=org.jboss.system.server.jmx.MBeanServerBuilderImpl"
JAVA_OPTS="$JAVA_OPTS -Djboss.platform.mbeanserver"
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote"
I'm using JDK 1.6.0_01-b06
I have honestly never tried this remoting approach. But, if both your client machine and the server happen to both be linux boxes or similar *nixes with SSH, then you can ssh -XCA to the server and start JConsole on the server and have the GUI display on your client machine with X port forwarding. A JConsole running locally to the server JVM you want to monitor should not have any trouble connecting.
I personally think that's a nifty trick but I realize that it dosn't really solve the problem of getting JConsole to connect remotely through JWS.
First thing I would do is to delete both /tmp and /work directories under JBoss /default and redeploy the WAR. If that doesn't, I would upgrade the JDK to use a more recent version of 1.6. 1.6.0_01 is pretty old.
I'm not sure if there's a specific reason you're trying to use WS to access the mbean server, but with JConsole you can directly access a remote JVM. To do this use "service:jmx:rmi:///jndi/rmi://<remote-machine>:<port>/jmxrmi" (where <remote-machine> is whatever machine your trying to connect to and <port> is 11099) as the remote process.
I have used this to connect to any 1.6 JVM that exposes an mbean server (JBoss, ActiveMQ, etc).
I don't know if this is related, but JBoss has a tendency to redirect to itself. If you connect to a host, say jboss.localdomain:3873, wanting to connect to a ejb, JBoss might lookup its own hostname and redirect to the address it gets from there. If you have a public hostname, it might find that instead (say jboss.publicdomain.com), and tell the client to reconnect to jboss.publicdomain.com:1099. Depending on your DNS, this might or might not be a reachable address from your client.
There are various varations of this problem, and as a bonus, sometimes the initial "connection check" works, so the client app deploys, but fails later on connect.
Had a similar issue, but with JBoss Seam: take a look at JBSEAM-4029. As one of the workarounds it suggests to override the class running into the NPE - in Seam's case the JBossClusterMonitor.
I bet the JWS code is running into exact same issue, i.e. ending up calling MBeanServerFactory.findMBeanServer(null) at some point in time. The stack trace should reveal which exact class does this.

Categories

Resources