Accessing a remote MBean server - java

I am running a client/server application using JBoss.
How can I connect to the server JVM's MBeanServer? I want to use the MemoryMX MBean to track the memory consumption.
I can connect to the JBoss MBeanServer using JNDI lookup but the java.lang.MemoryMX MBean is not registered with the JBoss MBeanServer.
EDIT: The requirement is for programmatic access to the memory usage from the client.

I wrote a class like this:
import javax.management.remote.JMXServiceURL;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanInfo;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
public class JVMRuntimeClient
{
static void main(String[] args) throws Exception
{
if (args == null)
{
System.out.println("Usage: java JVMRuntimeClient HOST PORT");
}
if(args.length < 2)
{
System.out.println("Usage: java JVMRuntimeClient HOST PORT");
}
try
{
JMXServiceURL target = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://"+args[0]+":"+args[1]+"/jmxrmi");
JMXConnector connector = JMXConnectorFactory.connect(target);
MBeanServerConnection remote = connector.getMBeanServerConnection();
/**
* this is the part where you MUST know which MBean to get
* com.digitalscripter.search.statistics:name=requestStatistics,type=RequestStatistics
* YOURS WILL VARY!
*/
ObjectName bean = new ObjectName("com.digitalscripter.search.statistics:name=requestStatistics,type=RequestStatistics");
MBeanInfo info = remote.getMBeanInfo(bean);
MBeanAttributeInfo[] attributes = info.getAttributes();
for (MBeanAttributeInfo attr : attributes)
{
System.out.println(attr.getDescription() + " " + remote.getAttribute(bean,attr.getName()));
}
connector.close();
}
catch(Exception e)
{
System.out.println(e.getMessage());
System.exit(0);
}
}
}

Unlike the JBoss server's MBeanServer, the JVM's MBean server doesn't allow remote monitoring by default. You need to set various system properties to allow that:
http://java.sun.com/javase/6/docs/technotes/guides/management/agent.html

A code example from an IBM article: link
MBeanServerConnection serverConn;
try {
//connect to a remote VM using JMX RMI
JMXServiceURL url = new JMXServiceURL( "service:jmx:rmi:///jndi/rmi://<addr>");
JMXConnector jmxConnector = JMXConnectorFactory.connect(url);
serverConn = jmxConnector.getMBeanServerConnection();
ObjectName objName = new
ObjectName(ManagementFactory.RUNTIME_MXBEAN_NAME);
// Get standard attribute "VmVendor"
String vendor =
(String) serverConn.getAttribute(objName, "VmVendor");
} catch (...) { }

Have you tried launching a JConsole (is $JAVA_HOME/bin) to connect with the server? You should be able to view memory stats from there

The following code lists all mbeans of a given (jmx enabled) java application with their attributes and operations grouped by the domain. Just start the java app you wanna monitor with a fixed jmx port, e.g. by using these vm parameters:
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=9000
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
Then run this main:
import javax.management.*;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import java.io.IOException;
public class JmxListAll {
public static void main(String[] args) throws IOException, MalformedObjectNameException, IntrospectionException, InstanceNotFoundException, ReflectionException {
/*
1. JMXServiceURL.
*/
String jmxHost = "localhost:9000"; // exactly like jconsole localhost:9026
String url = "service:jmx:rmi:///jndi/rmi://" + jmxHost + "/jmxrmi";
JMXServiceURL serviceURL = new JMXServiceURL(url);
/*
2. JMXConnector and the actual serverConnection
*/
JMXConnector connector = JMXConnectorFactory.connect(serviceURL);
MBeanServerConnection serverConnection = connector.getMBeanServerConnection();
/*
3. Walk through the domains and their objects
*/
System.out.println("\n Now we have a look at " + serverConnection.getMBeanCount() + " mbeans!");
int objectCount = 0;
for (String domain : serverConnection.getDomains()) {
System.out.println("\n***********************************************************************************");
System.out.println("DOMAIN: " + domain);
// query all the beans for this domain using a wildcard filter
for (ObjectName objectName : serverConnection.queryNames(new ObjectName(domain + ":*"), null)) {
System.out.println(" objectName " + ++objectCount + ": " + objectName);
MBeanInfo info = serverConnection.getMBeanInfo(objectName);
for (MBeanAttributeInfo attr : info.getAttributes()) {
System.out.print(" attr: " + attr.getDescription());
try {
String val = serverConnection.getAttribute(objectName, attr.getName()).toString();
System.out.println(" -> " + abbreviate(val));
} catch (Exception e) {
System.out.println(" FAILED: " + e);
}
}
for (MBeanOperationInfo op : info.getOperations()) {
System.out.println(" op: " + op.getName());
}
}
}
}
static String abbreviate(String text) {
if (text != null && text.length() > 42) {
return text.substring(0, 42) + "...";
} else {
return text;
}
}
}
As you should see, in the java.lang domain are several memory related mbeans. Pick the one you need.

Related

How do i know if my application is running in weblogic in debug mode?

Say that i want my application to behave differently when running in debug mode in WebLogic - is there a flag that i can check?
ie:
if (weblogic.DEBUG) Console.writeline("running in debug mode in weblogic");
You can add arguments to your weblogic server to allow you to debug it remotely, specifically by setting the -Xdebug option in your startWebLogic script.
You can see a full example in the Oracle docs here
And in a similar question here: How to debug Java EE application using WebLogic 10.3
Once you have debug turned on you could pull it out of the JVM args/system properties like shown here: How to get vm arguments from inside of java application?
If you're not asking about debug but instead asking how to tell if your server is in production mode vs development mode, you can also access isProductionModeEnabled() via JMX, as described here
You can also edit the logging levels for your servers to turn debug on...
You can use the DomainRuntimeServiceMBean and ServerRuntimeMBean provided by weblogic. There is an example on the oracle website of invoking these 2 MBeans to get the status of the server. I've pasted it below. Source can be found here
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Hashtable;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import javax.naming.Context;
public class PrintServerState {
private static MBeanServerConnection connection;
private static JMXConnector connector;
private static final ObjectName service;
// Initializing the object name for DomainRuntimeServiceMBean
// so it can be used throughout the class.
static {
try {
service = new ObjectName(
"com.bea:Name=DomainRuntimeService,Type=weblogic.management.
mbeanservers.domainruntime.DomainRuntimeServiceMBean");
}catch (MalformedObjectNameException e) {
throw new AssertionError(e.getMessage());
}
}
/*
* Initialize connection to the Domain Runtime MBean Server
*/
public static void initConnection(String hostname, String portString,
String username, String password) throws IOException,
MalformedURLException {
String protocol = "t3";
Integer portInteger = Integer.valueOf(portString);
int port = portInteger.intValue();
String jndiroot = "/jndi/";
String mserver = "weblogic.management.mbeanservers.domainruntime";
JMXServiceURL serviceURL = new JMXServiceURL(protocol, hostname,
port, jndiroot + mserver);
Hashtable h = new Hashtable();
h.put(Context.SECURITY_PRINCIPAL, username);
h.put(Context.SECURITY_CREDENTIALS, password);
h.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES,
"weblogic.management.remote");
connector = JMXConnectorFactory.connect(serviceURL, h);
connection = connector.getMBeanServerConnection();
}
/*
* Print an array of ServerRuntimeMBeans.
* This MBean is the root of the runtime MBean hierarchy, and
* each server in the domain hosts its own instance.
*/
public static ObjectName[] getServerRuntimes() throws Exception {
return (ObjectName[]) connection.getAttribute(service,
"ServerRuntimes");
}
/*
* Iterate through ServerRuntimeMBeans and get the name and state
*/
public void printNameAndState() throws Exception {
ObjectName[] serverRT = getServerRuntimes();
System.out.println("got server runtimes");
int length = (int) serverRT.length;
for (int i = 0; i < length; i++) {
String name = (String) connection.getAttribute(serverRT[i],
"Name");
String state = (String) connection.getAttribute(serverRT[i],
"State");
System.out.println("Server name: " + name + ". Server state: "
+ state);
}
}
public static void main(String[] args) throws Exception {
String hostname = args[0];
String portString = args[1];
String username = args[2];
String password = args[3];
PrintServerState s = new PrintServerState();
initConnection(hostname, portString, username, password);
s.printNameAndState();
connector.close();
}
}
You can the see debug socket log in the weblogic console like below,
Listening for transport dt_socket at address: xxxx
where xxxx is port number. By default the port number would be 8453

connecting client-server RMI

I am confused on how the client actually makes the connection to the server if the server is remote(not on the same machine as the client). My code works fine using localhost but i cant figure out how the client actually makes the connection to the server host so that it looks up the rmiregistry. I'm confused on what gets stored in the registry for the server, is it Sample or localhost? This may be dumb but i tried to convert localhost to its ipaddress on the client side and do String url = "//" + server + ":" + 1099 + "/Sample"; where server is the ip from getbyname() but i get a exception: java.rmi.NotBoundException: 127.0.0.1:1099/Sample
That was with the client and server on both machines. I'm just trying to figure out how the two connect remotely but it didn't even work on the same machine using the ip address of localhost.
Client:
import java.net.InetAddress;
import java.rmi.Naming;
import java.rmi.RemoteException;
public class SampleClient {
public static void main(String args[]) {
String url = "//" + "localhost" + ":" + 1099 + "/Sample";
SampleInterface sample = (SampleInterface)Naming.lookup(url);
} catch(Exception e) {
System.out.println("SampleClient exception: " + e);
}
}
}
Server:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.RMISecurityManager;
import java.rmi.server.UnicastRemoteObject;
public class SampleServer {
public static void main(String args[]) throws IOException {
// Create and install a security manager
if (System.getSecurityManager() == null)
System.setSecurityManager(new RMISecurityManager());
try {
String url = "//localhost:" + 1099 + "/Sample";
System.out.println("binding " + url);
Naming.rebind(url, new Sample());
// Naming.rebind("Sample", new Sample());
System.out.println("server " + url + " is running...");
}
catch (Exception e) {
System.out.println("Sample server failed:" + e.getMessage());
}
}
}
The server should bind to a Registry running on 'localhost'.
The client should lookup a Registry at the server host.
It's as simple as that.
I'm confused on what gets stored in the registry for the server, is it Sample or localhost?
Neither. You're confusing three different things:
The hostname, in this case 'localhost'.
The bind-name, in this case 'Sample'.
The object which is bound, which is the remote stub.

RMI(java.net.ConnectException: Connection refused: connect)

I am trying to run my server named SampleServer. I am using windows and this is what i did:
in cmd:
javaw rmiregistry 1099
cd C:\Users\Home\workspace\RMI\src
java -Djava.security.policy=policy SampleServer 1099
i get the following error:
binding //localhost:1099/Sample
New instance of Sample created
Sample server failed:Connection refused to host: localhost; nested exception is:
java.net.ConnectException: Connection refused: connect
I've tried using a different port # such as 4719 for rmiregistry but i receive the same error. I made sure that my firewall was disabled but the problem persist. I made sure that the port is not already being used. I really hope someone can help me.
Picture of my desktop with folders of project, eclipse window and cmd open:
http://s22.postimg.org/uq00qzslr/picyture.png
Code:
SampleServer:
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.RMISecurityManager;
import java.rmi.server.UnicastRemoteObject;
public class SampleServer {
public static void main(String args[]) {
if (args.length != 1) {
System.err.println("usage: java SampleServer rmi_port");
System.exit(1);
}
// Create and install a security manager
if (System.getSecurityManager() == null)
System.setSecurityManager(new RMISecurityManager());
try {
// first command-line argument is the port of the rmiregistry
int port = Integer.parseInt(args[0]);
String url = "//localhost:" + port + "/Sample";
System.out.println("binding " + url);
Naming.rebind(url, new Sample());
// Naming.rebind("Sample", new Sample());
System.out.println("server " + url + " is running...");
}
catch (Exception e) {
System.out.println("Sample server failed:" + e.getMessage());
}
}
}
SampleClient:
import java.rmi.Naming;
import java.rmi.RemoteException;
public class SampleClient {
public static void main(String args[]) {
try {
if (args.length < 3) {
System.err.println("usage: java SampleClient host port string... \n");
System.exit(1);
}
int port = Integer.parseInt(args[1]);
String url = "//" + args[0] + ":" + port + "/Sample";
System.out.println("looking up " + url);
SampleInterface sample = (SampleInterface)Naming.lookup(url);
// args[2] onward are the strings we want to reverse
for (int i=2; i < args.length; ++i)
// call the remote method and print the return
System.out.println(sample.invert(args[i]));
} catch(Exception e) {
System.out.println("SampleClient exception: " + e);
}
}
}
SampleInterface:
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface SampleInterface extends Remote {
public String invert(String msg) throws RemoteException;
}
Sample:
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.server.*;
// this is the class with remote methods
public class Sample
extends UnicastRemoteObject
implements SampleInterface {
private int a;
public Sample() throws RemoteException {
System.out.println("New instance of Sample created");
a = 1;
}
public String invert(String m) throws RemoteException {
// return input message with characters reversed
System.out.println("invert("+m+") a=" + a);
return new StringBuffer(m).reverse().toString();
}
}
policy:
grant {
permission java.security.AllPermission;
};
javaw rmiregistry 1099
Stop right there. This is already wrong. 'rmiregistry' is an executable, not the name of a Java class you can execute with 'java' or 'javaw'. Just use 'rmiregistry'.
This error occurs when there is no service running on the port, you are trying to connect. As said by EJP, rmiregistry is a tool which can be started by rmiregistry & in the background (JDK 7). I would recommend you that you check your firewall or connectivity issue with the port.

Get default gateway in java

I want to fetch default gateway for local machine using java. I know how to get it by executing dos or shell commands, but is there any another way to fetch?
Also need to fetch primary and secondary dns ip.
My way is:
try(DatagramSocket s=new DatagramSocket())
{
s.connect(InetAddress.getByAddress(new byte[]{1,1,1,1}), 0);
return NetworkInterface.getByInetAddress(s.getLocalAddress()).getHardwareAddress();
}
Because of using datagram (UDP), it isn't connecting anywhere, so port number may be meaningless and remote address (1.1.1.1) needn't be reachable, just routable.
In Windows with the help of ipconfig:
import java.awt.Desktop;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URI;
public final class Router {
private static final String DEFAULT_GATEWAY = "Default Gateway";
private Router() {
}
public static void main(String[] args) {
if (Desktop.isDesktopSupported()) {
try {
Process process = Runtime.getRuntime().exec("ipconfig");
try (BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(process.getInputStream()))) {
String line;
while ((line = bufferedReader.readLine()) != null) {
if (line.trim().startsWith(DEFAULT_GATEWAY)) {
String ipAddress = line.substring(line.indexOf(":") + 1).trim(),
routerURL = String.format("http://%s", ipAddress);
// opening router setup in browser
Desktop.getDesktop().browse(new URI(routerURL));
}
System.out.println(line);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Here I'm getting the default gateway IP address of my router, and opening it in a browser to see my router's setup page.
There is not an easy way to do this. You'll have to call local system commands and parse the output, or read configuration files or the registry. There is no platform independent way that I'm aware of to make this work - you'll have to code for linux, mac and windows if you want to run on all of them.
See How can I determine the IP of my router/gateway in Java?
That covers the gateway, and you could use ifconfig or ipconfig as well to get this. For DNS info, you'll have to call a different system command such as ipconfig on Windows or parse /etc/resolv.conf on Linux or mac.
There is currently no standard interface in Java to obtain the default gateway or the DNS server addresses. You will need a shell command.
I'm not sure if it works on every system but at least here I found this:
import java.net.InetAddress;
import java.net.UnknownHostException;
public class Main
{
public static void main(String[] args)
{
try
{
//Variables to find out the Default Gateway IP(s)
String canonicalHostName = InetAddress.getLocalHost().getCanonicalHostName();
String hostName = InetAddress.getLocalHost().getHostName();
//"subtract" the hostName from the canonicalHostName, +1 due to the "." in there
String defaultGatewayLeftover = canonicalHostName.substring(hostName.length() + 1);
//Info printouts
System.out.println("Info:\nCanonical Host Name: " + canonicalHostName + "\nHost Name: " + hostName + "\nDefault Gateway Leftover: " + defaultGatewayLeftover + "\n");
System.out.println("Default Gateway Addresses:\n" + printAddresses(InetAddress.getAllByName(defaultGatewayLeftover)));
} catch (UnknownHostException e)
{
e.printStackTrace();
}
}
//simple combined string out the address array
private static String printAddresses(InetAddress[] allByName)
{
if (allByName.length == 0)
{
return "";
} else
{
String str = "";
int i = 0;
while (i < allByName.length - 1)
{
str += allByName[i] + "\n";
i++;
}
return str + allByName[i];
}
}
}
For me this produces:
Info:
Canonical Host Name: PCK4D-PC.speedport.ip
Host Name: PCK4D-PC
Default Gateway Leftover: speedport.ip
Default Gateway Addresses:
speedport.ip/192.168.2.1
speedport.ip/fe80:0:0:0:0:0:0:1%12

Programmatically Enable/Disable Port on Network Switch

Greetings!
I am trying to find a way in Java to programmatically enable/disable a port on a network switch over SNMP. I tried using SNMP4J but couldn't get much help on the mailing list on how to use it. I'm not too concerned what library is used (open source vs commercial) as long as it gets the job done.
The switch I am trying to work with is a Cisco 3750 switch.
Regards,
James
You can use following simple code to enable/disable switch port using snmp4j.
It enables port 1 and disables port 6.
package com.mobinet.snmp;
import org.snmp4j.CommunityTarget;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.TransportMapping;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.Integer32;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultTcpTransportMapping;
/**
*
* #author batbayar
*/
public class SnmpTest {
private String address = "192.168.1.254/161"; // switch address and snmp port
private String writeCommunity = "myCommunityWrite"; // write community name
private Snmp snmp;
private CommunityTarget target;
public SnmpTest() {
try {
TransportMapping transport = new DefaultTcpTransportMapping();
snmp = new Snmp(transport);
Address targetAddress = GenericAddress.parse(address);
target = new CommunityTarget();
target.setCommunity(new OctetString(writeCommunity));
target.setAddress(targetAddress);
target.setRetries(2);
target.setTimeout(1500);
target.setVersion(SnmpConstants.version2c);
PDU command = new PDU();
command.setType(PDU.SET);
command.add(new VariableBinding(new OID("1.3.6.1.2.1.2.2.1.7.1"), new Integer32(2))); // port 1 down
command.add(new VariableBinding(new OID("1.3.6.1.2.1.2.2.1.7.6"), new Integer32(1))); // port 6 up
ResponseEvent response = snmp.send(command, target);
System.out.println("response: " + response);
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
SnmpTest test = new SnmpTest();
}
}
I have had good luck with the Westhawk Java SNMP stack.
For a simple SNMP set, the syntax will look something like this:
public static boolean setOid(String hostAddress, int portNumber, String communityName, String oidToSet, String valueToSet) {
SnmpContextPool context = null;
try {
context = new SnmpContextPool(hostAddress, portNumber, SnmpContextFace.STANDARD_SOCKET);
context.setCommunity(communityName);
SetPdu oneSetPdu = new SetPdu(context);
AsnObject obj = new AsnOctets(valueToSet); // use AsnInteger here if you are setting an integer value
oneSetPdu.addOid(oidToSet, obj);
return oneSetPdu.send();
} catch (Exception e) {
//TODO: Handle exceptions properly
e.printStackTrace();
} finally {
if (context != null) {
context.destroy();
}
}
return false;
}
You could try reading the docs...
A (nearly) complete example for the
SNMP4J API usage is the console tool.
It can be found in the
org.snmp4j.tools.console.SnmpRequest
class.

Categories

Resources