Runtime class loading

I'm working on an application and I need to do something kind of tricky. The classes needed to run will vary depending on what a user selects in the gui. If one thing is selected use these classes, if the other thing is selected use these other classes. The worst part of all this is that the jar files that contain the different classes interfere with each other. So if I put all of the jars in the classpath it stops working.

So what I'd like to do is use the URLClassLoader, if possible. So in my code I have this:

File root = new File(System.getProperty("user.dir"),"lib");

File[] jars = root.listFiles();

URL[] urls = new URL[jars.length];

for(int i=0;i<jars.length;i++) {

urls = jars.toURL();

}

loader = URLClassLoader.newInstance(urls,Main.class.getClassLoader());

In the File(System.getProperty("user.dir"),"lib") directory I put the jar files and it seems to be loading properly. But now what?Do I specifically load each class before I can use it using loader.loadClass()?>

[1066 byte] By [sasdava] at [2007-10-3 0:37:03]
# 1
i love this. i love all of this.
TuringPesta at 2007-7-14 17:30:53 > top of Java-index,Java Essentials,Java Programming...
# 2

> I'm working on an application and I need to do

> something kind of tricky.

Ill work from the premise that you know what youre doing and that indeed dynamic classloading is the correct solution to your problem.

But to be safe, if you doubt its the best or only solution you should run it by us.

> The worst part of all this is that the jar files

> that contain the different classes interfere with

> each other. So if I put all of the jars in the

> classpath it stops working.

why? you should be more specific about whats going on.

> But now what?Do I specifically

> load each class before I can use it using

> loader.loadClass()?

You will and you wont. If a class depends on another class the RESOLVE flag in a Classloaders load() method will load those classes.

It'd be bad form to rely totally on this resolve feature to load all your classes - so YES you have to load every class.

Ive done a lot of custom classloader stuff. Look into writing a custom classloader (there are many great tutorials by googling "java custom classloader"). Also keep in mind the problems that arise between classes loaded by different classloaders (as in the System classloader and your new custom one) and see if they might come up in whatever it is you are doing.

There isnt much advice beyond that b.c. you havent really explained what you are doing.

TuringPesta at 2007-7-14 17:30:53 > top of Java-index,Java Essentials,Java Programming...
# 3

OK, more detail.

The application I'm developing is an MBean browser for WebSphere and WebLogic. Eventually I'll probably add JBoss to it but that's for the future.

Each application server requires it's own jar files be included in the classpath in order to establish the connection from the java application to the server. For WebLogic you need the weblogic.jar file and for WebSphere there is a list of about 19 jars to include. Both of the application servers support only version 1.0 of JMX, so I'm forced to use JDK 1.4. If I try anything higher the JMX classes included in the JDK, which are version 1.2, cause errors when connecting to the server.

In addition, if I have the weblogic.jar file in my classpath when I connect to a WebSphere server there are problems. For example, the connection is established but queries fail. Yes, I'm sure it's the weblogic.jar that causes the failure because when that is NOT in the classpath everything works to perfection.

So, I was hoping I could do this type of dynamic loading of the jar files, rather than including everything in the classpath.

By the way, I did try the Classloaders loadClass() method with the resolve flag and I was told it's protected.

Thanks for the help

sasdava at 2007-7-14 17:30:53 > top of Java-index,Java Essentials,Java Programming...
# 4

first let me start by saying im not really qualified to help you b.c. im not familiar with WebSphere or WebLogic etc.

that being said, what im thinking is: this is NOT a case for dynamic classloading.

i may be totally misunderstanding what you are doing so ill repeat what i think is going on:

- you are having problems loading WS and WL together b.c. you claim that their jar files in the classpath are poison, lol.

- you are writing a program that communicates with WS and WL

- will your program communicate with both at the same time?

im a fan of a simple answer over eloborate schemes that can bite you later so id say: start the 3 apps (WS, WL, yours) with three different JVMs. You can have your program run a script that launches the other two. Now you just have to handle communication between your program and those.

The benefit is you can run your programs JVM as 1.5 or higher and have the other 2 run on the older JVM. Just keep the old JRE in a folder and have the run scrpt point to it. When you deploy you can provide the old JRE and let the program run on your users own JVM 1.4 or higher.

TuringPesta at 2007-7-14 17:30:53 > top of Java-index,Java Essentials,Java Programming...
# 5
Whatever happened with this?
TuringPesta at 2007-7-14 17:30:53 > top of Java-index,Java Essentials,Java Programming...
# 6

Sorry for the delay in getting back on this but vacation interferred with my fun :)

Yes, my application communicates with both WS and WL, and in the future with other application servers.

No, it won't be attached to both servers at the same time, but there may be time when I would be required to log on to one, log off, then log on to the other in the same session.

All three already run in different JVMs. In fact, they are running on different machines. WS and WL run in 1.4 and the JVM they use is included in their installations. So the only JVM I can control is the one running my application. And it has to be 1.4 because of the version of JMX WS and WL support in the versions of WS and WL my application is connecting to.

sasdava at 2007-7-14 17:30:53 > top of Java-index,Java Essentials,Java Programming...
# 7

Well, I spent most of today working on it and I'm not any closer than I was a week ago.

Here's where I go wrong:

At this point in my code

if(serverType.equalsIgnoreCase("weblogic")) {

rmbs = new WebLogicServerInstance();

}

else if(serverType.equalsIgnoreCase("websphere")) {

rmbs = new WebSphereServerInstance();

}

I'm trying to use a static initializer in the WebLogicServerInstance, it looks like this:

static {

try {

File root = new File(System.getProperty("user.dir")+File.separator+"lib","weblogic.jar");

urlLoader = new URLClassLoader(new URL[] { root.toURL() } );

urlLoader.loadClass("javax.management.AttributeNotFoundException");

urlLoader.loadClass("javax.management.InstanceNotFoundException");

urlLoader.loadClass("javax.management.MalformedObjectNameException");

urlLoader.loadClass("javax.management.MBeanAttributeInfo");

urlLoader.loadClass("javax.management.MBeanException");

urlLoader.loadClass("javax.management.MBeanInfo");

urlLoader.loadClass("javax.management.MBeanServer");

urlLoader.loadClass("javax.management.ObjectInstance");

urlLoader.loadClass("javax.management.ObjectName");

urlLoader.loadClass("javax.management.ReflectionException");

urlLoader.loadClass("weblogic.management.Helper");

urlLoader.loadClass("weblogic.management.MBeanHome");

urlLoader.loadClass("weblogic.management.WebLogicMBean");

}

catch(Exception ex) {

ex.printStackTrace();

}

}

and what I'm getting is

java.lang.NoClassDefFoundError: javax/management/MBeanServer

at mbeanbrowser.MBeanBrowserMainWindow.login(MBeanBrowserMainWindow.java:191)

Line 191 is rmbs = new WebLogicServerInstance();

So it looks like one of three things.

First, the static initializer isn't being run. I tried adding a System.out.println("Initializer"); to the top of it and it never prints it. So maybe that is the problem. But I also tried a constructor instead of a static initializer and got exactly the same results at exactly the same point.

Second, you can't us URLClassLoader to load jar files that are not in the classpath. According to all my research (Google is a nice tool for developers) URLClassLoader CAN load jar files that are not in the classpath. So I hope I'm wrong about that one.

Third, I am too stupid to live. Right now my brain has turned to oatmeal so that's the way I'm leaning.

Any help for me or am I lost in the woods?

sasdava at 2007-7-14 17:30:53 > top of Java-index,Java Essentials,Java Programming...
# 8

1) The code is failing in the initializer. That's running when the class is loaded for the first time. That's part of the trace is telling you where that is happening. There is probably some more in the stack trace where you would see it failing to execute the code in the initializer.

This is sort of a minor point but just wanted to mention.

2) Have you noticed that javax.management.MBeanServer is an interface? I mean don't you want MBeanServerFactory?

3) I hope not, oatmeal is soggy.

cotton.ma at 2007-7-14 17:30:53 > top of Java-index,Java Essentials,Java Programming...
# 9

1. Here's the full stacktrace. If there is any helpful information in it I don't see it.

java.lang.NoClassDefFoundError: javax/management/MBeanServer

at mbeanbrowser.MBeanBrowserMainWindow.login(MBeanBrowserMainWindow.java:191)

at mbeanbrowser.MBeanBrowserMainWindow.access$200(MBeanBrowserMainWindow.java:54)

at mbeanbrowser.MBeanBrowserMainWindow$1.actionPerformed(MBeanBrowserMainWindow.java:107)

at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1786)

at javax.swing.AbstractButton$ForwardActionEvents.actionPerformed(AbstractButton.java:1839)

at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:420)

at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:258)

at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:245)

at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:231)

at java.awt.Component.processMouseEvent(Component.java:5100)

at java.awt.Component.processEvent(Component.java:4897)

at java.awt.Container.processEvent(Container.java:1569)

at java.awt.Component.dispatchEventImpl(Component.java:3615)

at java.awt.Container.dispatchEventImpl(Container.java:1627)

at java.awt.Component.dispatchEvent(Component.java:3477)

at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:3483)

at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3198)

at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3128)

at java.awt.Container.dispatchEventImpl(Container.java:1613)

at java.awt.Window.dispatchEventImpl(Window.java:1606)

at java.awt.Component.dispatchEvent(Component.java:3477)

at java.awt.EventQueue.dispatchEvent(EventQueue.java:480)

at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:201)

at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151)

at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:145)

at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:137)

at java.awt.EventDispatchThread.run(EventDispatchThread.java:100)

2. I tried MBeanServerFactory instead of MBeanServer and got exactly the same error.

3. I hope not too. I hate oatmeal.

sasdava at 2007-7-14 17:30:53 > top of Java-index,Java Essentials,Java Programming...
# 10

What you need to grasp is that class loaders generally form a heirarchy. When you create a URLClassLoader, generally, it will only load classes itself which

aren't on the classpath, any that are it will delegate to the system class loaders. Once a class loader has loaded a class, that class will use that loader to load any classes is references.

Therefore there should be no need to explicitly load a whole bunch of classes.

Create a URLClassLoader which points to whichever library jar you want. Then, rather than loading all these utility classes you need to have the URLClassLoader load the class which references all these utility classes, which means that the class in question must not be on the class path.

You may want to create another URLClassLoader pointing to the location of the class that uses the library, intialising it with it's parent defined as the library ClassLoader.

References on a chain of class loaders are allowed only towards the system class loader, anything loaded from the classpath can't reference stuff from the URLClassLoader.

malcolmmca at 2007-7-14 17:30:53 > top of Java-index,Java Essentials,Java Programming...
# 11

Yes, this is pretty much what I figured out during my struggle, and what I'm doing as well.

Currently I have nothing in my classpath, either on the commandline or as an environment variable. Also nothing in my lib\ext. I'm letting the system classloader load everything needed for the GUI, and I'm trying to load everything needed for JMX using the URLClassLoader. So for now my URLClassLoader is loading on jar file (weblogic.jar) and then attempting to load all of the JMX classes. But I'm getting the stacktrace I posted before and I can't figure out where it's happening or why.

sasdava at 2007-7-14 17:30:53 > top of Java-index,Java Essentials,Java Programming...
# 12

How are you loading the class mbeanbrowser.MBeanBrowserMainWindow?

If that's loading as part of your main application stuff it won't be able to reference anything from your URLClassLoader. Classes loaded by the system class loader can't. A class can only reference classes loaded by the same classloader or one of it's parents, and that means the classloader that actually loaded it, not the one you requested it from.

When I've done this kind of thing I have a small main class, which creates URLClassLoaders one of which loads the real application from a completely separate code source and runs it.

Granted it's rather tiresome to set up, with two separate build directories, but it really is the only way I've found.

malcolmmca at 2007-7-14 17:30:53 > top of Java-index,Java Essentials,Java Programming...
# 13
I'm not sure I understand any of that, but does that explain why the static initializer isn't working?
sasdava at 2007-7-14 17:30:53 > top of Java-index,Java Essentials,Java Programming...
# 14
More oddness,I just ran it all again with -verbose and it's showing:[Loaded mbeanbrowser.WebLogicServerInstance]Doesn't that mean the static initializer should have run?
sasdava at 2007-7-14 17:30:53 > top of Java-index,Java Essentials,Java Programming...
# 15

Maybe I'm not giving enough information. The class where the static initializer is failing implements an interface. The interface looks like this:

public interface ServerBeanInstance {

public void login(String host, String port, String username, String password) throws MBeanException;

public MBeanServer getMBeanServer() throws MBeanException;

public Set getDomains() throws MBeanException;

public Set getTypes(Object domain) throws MBeanException, MalformedObjectNameException ;

public Set getMBeans(Object domain,Object type) throws MBeanException, MalformedObjectNameException;

public Object getAttribute(ObjectName objName, String name) throws MBeanException, AttributeNotFoundException, InstanceNotFoundException, ReflectionException;

public MBeanAttributeInfo[] getAttributes(ObjectName objectName) throws MBeanException, AttributeNotFoundException, InstanceNotFoundException, ReflectionException;

}

Am I trying something that can't be done or have I run into a bug of some kind?

sasdava at 2007-7-21 9:13:03 > top of Java-index,Java Essentials,Java Programming...
# 16

You are, I think, referencing a whole stack of classes and interfaces which are present in the URLClassLoader but not the system class loader. If your class is on the class path it can only reference classes loaded by the sytem class loader. It will give you a class not found exception when it tries to resolve references to your special library classes.

What you probably need to do is to generate two separate jars or class directories. The one containing your main class cannot reference any of these library routines, directly or otherwise. The other contains your real application classes which do.

The main class creates the URLClassLoaders, as discussed, and calls loadClass on them to get the real application class (which is not on the classpath). Then it invokes it by reflection, without having any reference to it.

Then your application classes will be loaded by a ClassLoader that can access the library classes you need and their references will be filled successfully.

malcolmmca at 2007-7-21 9:13:03 > top of Java-index,Java Essentials,Java Programming...
# 17

Let's see if I'm understanding.

Here's my Main class

public class Main {

private static URLClassLoader classLoader;

public Main() throws Exception {

File root = new File(System.getProperty("user.dir")+File.separator);

classLoader = new URLClassLoader(new URL[] {root.toURL()});

Class c = classLoader.loadClass("mbeanbrowser.MBeanBrowserMainWindow");

MBeanBrowserMainWindow mainWindow = (MBeanBrowserMainWindow) c.newInstance();

mainWindow.pack();

mainWindow.setVisible(true);

}

public static URLClassLoader getLoader() {

return classLoader;

}

public static void main(String[] args) {

try {

new Main();

}

catch(Exception ex) {

ex.printStackTrace();

System.exit(1);

}

}

}

Is this headed in the right direction? My MBeanBrowserMainWindow is displaying fine but I'm still getting the exact same error in the exact same way. What changes do I need to make to WebLogicServerInstance? The initializer is shown on reply 7 of 16.

Does it matter how I invoke Main? Right now I'm in the directory with Main.class and I invoke it with

c:\j2sdk1.4.2_12\bin\java Main

Also in this directory is a lib directory containing weblogic.jar

Thanks

sasdava at 2007-7-21 9:13:03 > top of Java-index,Java Essentials,Java Programming...
# 18

The trouble is you're still referencing the MBeanBrowserMainWindow class by using it in a variable declaration and cast. You can't reference it at all.

You don't need to, having created an instance cast it to JFrame (which it presumably extends) and set that visible.

The main class doesn't need to know exactly what class it is. Incidentally it's a good idea to set your classloader as the current thread's "context" class loader, which some indirect loading methods use.

Thread.currentThread().setContextClassloader(classLoader);

And note, this assumes that the class file for MBeanBrowserMainWindow.class is in the added directory, not on the classpath.

Mind you, AFAIKS, you are pointing the URLClassloader at the current directory, which probably is on the classpath (it's the default classpath). That doesn't look right.

malcolmmca at 2007-7-21 9:13:03 > top of Java-index,Java Essentials,Java Programming...
# 19

OK, here's my new Main class:

package starter;

import java.io.File;

import java.net.URL;

import java.net.URLClassLoader;

import javax.swing.JFrame;

import javax.swing.JOptionPane;

import javax.swing.UIManager;

public class Main {

public Main() throws Exception {

File root = new File(System.getProperty("user.dir")+File.separator);

URLClassLoader classLoader = new URLClassLoader(new URL[] {root.toURL()});

Thread.currentThread().setContextClassLoader(classLoader);

Class c = classLoader.loadClass("mbeanbrowser.MBeanBrowserMainWindow");

javax.swing.JFrame mainWindow = (javax.swing.JFrame) c.newInstance();

mainWindow.pack();

mainWindow.setVisible(true);

}

public static void main(String[] args) {

try {

new Main();

}

catch(Exception ex) {

ex.printStackTrace();

System.exit(1);

}

}

}

I'm invoking this by this command:

java -classpath build\classes starter.Main

The mainwindow comes up fine, the GUI looks just the same. But I am still getting the exact same error in the exact same place. Where am I going wrong here?

My understanding was that using the -classpath option would remove the current directory (D:\Code\Starter) from the classpath. Is that wrong?

I am pointing the URLClassLoader to the current directory, but where else could I point it and how?

sasdava at 2007-7-21 9:13:03 > top of Java-index,Java Essentials,Java Programming...
# 20
Where's the MBeanBrowserMainWindow.class file? Make sure there isn't one (even an obsolete one) on the classpath.I rarely write code using the current directory. You can put the path in in numerous ways, a System property, a properties file, whatever.
malcolmmca at 2007-7-21 9:13:03 > top of Java-index,Java Essentials,Java Programming...
# 21

I'm invoking the program like this:

java -Dbrowser.path=D:\Code\MBeanBrowser\build\classes -classpath build\classes starter.Main

It seems like it's almost working now that I changed the URLClassLoader in Main so that it is created like this:

File root = new File(System.getProperty("browser.path")+File.separator);

File root2 = new File(System.getProperty("browser.path")+File.separator+"lib"+File.separator+"weblogic.jar");

URLClassLoader classLoader = new URLClassLoader(new URL[] {root.toURL(),root2.toURL()});

Thread.currentThread().setContextClassLoader(classLoader);

And in WebLogicServerInstance I have this:

static {

System.out.println("Initializer");

try {

File root = new File(System.getProperty("browser.path")+File.separator+"lib"+File.separator+"weblogic.jar");

URLClassLoader urlLoader = new URLClassLoader(new URL[] { root.toURL() }, Thread.currentThread().getContextClassLoader());

urlLoader.loadClass("javax.management.AttributeNotFoundException");

urlLoader.loadClass("javax.management.InstanceNotFoundException");

urlLoader.loadClass("javax.management.MalformedObjectNameException");

urlLoader.loadClass("javax.management.MBeanAttributeInfo");

urlLoader.loadClass("javax.management.MBeanException");

urlLoader.loadClass("javax.management.MBeanInfo");

urlLoader.loadClass("javax.management.MBeanServer");

urlLoader.loadClass("javax.management.ObjectInstance");

urlLoader.loadClass("javax.management.ObjectName");

urlLoader.loadClass("javax.management.ReflectionException");

urlLoader.loadClass("weblogic.management.Helper");

urlLoader.loadClass("weblogic.management.MBeanHome");

urlLoader.loadClass("weblogic.management.WebLogicMBean");

}

catch(Exception ex) {

ex.printStackTrace();

}

}

With this in place the static initializer is running and the login starts, but I'm getting AssertionErrors on one of the internal classes.

Not the best solution, in my opinion, because I was hoping to create a separate class loader for the JMX classes.

sasdava at 2007-7-21 9:13:03 > top of Java-index,Java Essentials,Java Programming...
# 22

You definitely shouldn't need all those loadClass calls in the intialiser, the classes will be loaded automatically as they are referenced. In fact none of this intialisation code in the WebServerLogicInstance should be needed. It will have no effect anyway. You are loading these classes into a classloader which you then discard the reference to, which will discard the classes as well.

And you can have a separate classloader for your own code and for the library classes providing you make the library class loader the parent of the loader which loads your code.

The JVM has no central cache of loaded classes, each classloader instance caches the classes it loads itself. If ask a different classloader for the same class then, unless the first classloader is an ancestor of the second, it will attempt to load a new copy.

malcolmmca at 2007-7-21 9:13:03 > top of Java-index,Java Essentials,Java Programming...
# 23

OK, good. That was some information I didn't have before. Helpful as it is, though, it doesn't resolve the problem I'm having.

I've modified this program and experimented with more approaches than I've ever needed to for any problem and I'm still getting the same error in the same place, and as far as I can see I'm no closer to a resolution than I was when I first opened this post. This is getting frustrating.

sasdava at 2007-7-21 9:13:03 > top of Java-index,Java Essentials,Java Programming...
# 24
Hmm.. you are running on 1.5 aren't you? I notice the documentation for MBeanServer says "since 1.5" and that you don't use the new for syntax when you might.
malcolmmca at 2007-7-21 9:13:03 > top of Java-index,Java Essentials,Java Programming...
# 25
No, unfortunately. The versions of WebSphere and Weblogic my program is connecting to use JMX 1.0, so I'm forced to use 1.4.2.
sasdava at 2007-7-21 9:13:03 > top of Java-index,Java Essentials,Java Programming...
# 26

Then the MBeanServer thing isn't part of the standard API, and the question becomes one of access to the JMX library from the WebSphere stuff. Now I think you've put your JMX library in the URLClassLoader, in which case the Webspher e libraries also must be loaded via that route, rather than being on the classpath.

Or you could create another level of ClassLoader with the JMX one as it's parent to load websphere.

malcolmmca at 2007-7-21 9:13:03 > top of Java-index,Java Essentials,Java Programming...
# 27

Actually, I haven't gotten to the WebSphere side yet. Right now I'm still trying to get weblogic to work using this dynamic loading technique.

The JMX library is in the weblogic.jar file, so it is supposed to be loading from there. But it's not, obviously, because of the error.

When I get around to the WebSphere side I was planning on creating another URLClassLoader to handle the 19 jar files that WebSphere requires for this. The JMX library is in one of those files TOO, which is the reason I'm not putting all 20 of the jar files in the classpath and calling it quits. I've tried that and things blow up as soon as I do.

FYI, MBeanServer isn't loaded with new. For Weblogic, first you login with this:

String url = "t3://" + host + ":" + port;

MBeanHome localHome = Helper.getAdminMBeanHome(username, password, url);

Then you get the MBeanServer by calling a method from the MBeanHome class which returns javax.management.MBeanServer:

localHome.getMBeanServer();

But we're not getting that far, obviously.

For WebSphere the login process is completely different, but I'll get to that later, hopefully.

sasdava at 2007-7-21 9:13:03 > top of Java-index,Java Essentials,Java Programming...
# 28

I don't know much about WebLogic but, from the trace, it's happening very early in the process of loading WebLogicServerInstance, which suggests that WebLogicServerInstance probably implements or extends the offending class (check the API doc). If it were happening during initialisation the stack trace would show an <init> or <clinit> depending whether it was instance or class initialization.

Are you absolutely sure the class is in the same jar as the weblogic class?

malcolmmca at 2007-7-21 9:13:03 > top of Java-index,Java Essentials,Java Programming...
# 29

Which class do you mean? MBeanServer? Yes, I'm positive it's in there.

WebLogicServerInstance implements ServerBeanInstance. It's my own class and doesn't extent or implement anything else. I posted the code for it earlier but I'll put it in again here:

package mbeanbrowser;

import java.util.Set;

import javax.management.AttributeNotFoundException;

import javax.management.InstanceNotFoundException;

import javax.management.MalformedObjectNameException;

import javax.management.MBeanAttributeInfo;

import javax.management.MBeanException;

import javax.management.MBeanInfo;

import javax.management.MBeanServer;

import javax.management.ObjectName;

import javax.management.ReflectionException;

public interface ServerBeanInstance {

public void login(String host, String port, String username, String password) throws MBeanException;

public MBeanServer getMBeanServer() throws MBeanException;

public Set getDomains() throws MBeanException;

public Set getTypes(Object domain) throws MBeanException, MalformedObjectNameException ;

public Set getMBeans(Object domain,Object type) throws MBeanException, MalformedObjectNameException;

public Object getAttribute(ObjectName objName, String name) throws MBeanException, AttributeNotFoundException, InstanceNotFoundException, ReflectionException;

public MBeanAttributeInfo[] getAttributes(ObjectName objectName) throws MBeanException, AttributeNotFoundException, InstanceNotFoundException, ReflectionException;

}

I did it this way because the login to Weblogic and WebSphere are differnt, as I discussed before.

sasdava at 2007-7-21 9:13:03 > top of Java-index,Java Essentials,Java Programming...
# 30

Is your ServerBeanInstance class on the classpath by any chance? If the system loader loaded it it wouldn't then be able to reference MBeanServer. You need all your classes in the off-classpath directory except that main class.

I notice MBeanServer is the first JMX class referenced in this interface.

malcolmmca at 2007-7-21 9:13:09 > top of Java-index,Java Essentials,Java Programming...
# 31

I'm positive ServerBeanInstance isn't in the classpath. It's in mbeanbrowser along with MBeanBrowserMainWindow so the classloader created in Main should find it.

I notice MBeanServer was the first JMX class referenced too, so I moved that line to the bottom. MBeanException is the first one now and the error remains unchanged.

sasdava at 2007-7-21 9:13:09 > top of Java-index,Java Essentials,Java Programming...
# 32

I'm still tending to think your problem is due to an attempt by a class unexpectedly loaded by the system classloader to reference the class in the URLClassLoader.

At this level of deperation I'd resort to some serious logging. For example overload the loadClass method on your class loader so it logs classes loaded, and, for each, whether Class.getClassloader() points back to itself.

i.e whether it loaded the class itself or did it delegate it.

malcolmmca at 2007-7-21 9:13:09 > top of Java-index,Java Essentials,Java Programming...
# 33

I'm not sure if this is what you had in mind or not:

package starter;

import java.net.URL;

import java.net.URLClassLoader;

public class JarClassLoader extends URLClassLoader {

public JarClassLoader(URL[] urls) {

super(urls);

}

public Class loadClass(String name) throws ClassNotFoundException {

Class c = super.loadClass(name);

System.out.println(c.getClass().getName() + " loaded by " + c.getClassLoader());

return c;

}

}

And my Main class now looks like this:

package starter;

import java.io.File;

import java.net.URL;

import java.net.URLClassLoader;

import javax.swing.JFrame;

public class Main {

public Main() throws Exception {

File root = new File(System.getProperty("browser.path")+File.separator);

JarClassLoader classLoader = new JarClassLoader(new URL[] {root.toURL()});

Thread.currentThread().setContextClassLoader(classLoader);

Class c = classLoader.loadClass("mbeanbrowser.MBeanBrowserMainWindow");

javax.swing.JFrame mainWindow = (javax.swing.JFrame) c.newInstance();

classLoader.loadClass("mbeanbrowser.ServerBeanInstance");

mainWindow.pack();

mainWindow.setVisible(true);

}

public static void main(String[] args) {

try {

new Main();

}

catch(Exception ex) {

ex.printStackTrace();

System.exit(1);

}

}

}

Here's the output, hope it means more to you than it does to me:

java.lang.Class loaded by null

java.lang.Class loaded by starter.JarClassLoader@1893efe

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by starter.JarClassLoader@1893efe

java.lang.Class loaded by starter.JarClassLoader@1893efe

java.lang.Class loaded by starter.JarClassLoader@1893efe

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by starter.JarClassLoader@1893efe

java.lang.Class loaded by null

java.lang.Class loaded by starter.JarClassLoader@1893efe

java.lang.Class loaded by starter.JarClassLoader@1893efe

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by starter.JarClassLoader@1893efe

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by starter.JarClassLoader@1893efe

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by starter.JarClassLoader@1893efe

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by starter.JarClassLoader@1893efe

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.Class loaded by null

java.lang.NoClassDefFoundError: javax/management/MBeanServer

at mbeanbrowser.MBeanBrowserMainWindow.login(MBeanBrowserMainWindow.java:191)

at mbeanbrowser.MBeanBrowserMainWindow.access$200(MBeanBrowserMainWindow.java:54)

at mbeanbrowser.MBeanBrowserMainWindow$1.actionPerformed(MBeanBrowserMainWindow.java:107)

at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1786)

at javax.swing.AbstractButton$ForwardActionEvents.actionPerformed(AbstractButton.java:1839)

at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:420)

at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:258)

at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:245)

at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:231)

at java.awt.Component.processMouseEvent(Component.java:5100)

at java.awt.Component.processEvent(Component.java:4897)

at java.awt.Container.processEvent(Container.java:1569)

at java.awt.Component.dispatchEventImpl(Component.java:3615)

at java.awt.Container.dispatchEventImpl(Container.java:1627)

at java.awt.Component.dispatchEvent(Component.java:3477)

at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:3483)

at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3198)

at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3128)

at java.awt.Container.dispatchEventImpl(Container.java:1613)

at java.awt.Window.dispatchEventImpl(Window.java:1606)

at java.awt.Component.dispatchEvent(Component.java:3477)

at java.awt.EventQueue.dispatchEvent(EventQueue.java:480)

at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:201)

at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151)

at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:145)

at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:137)

at java.awt.EventDispatchThread.run(EventDispatchThread.java:100)

java.lang.Class loaded by null

I'm confused by the "loaded by null" statements. Does this mean that it's being loaded by the system classloader, as you suspected? Is there a better way to do this? Be gentle with me, it's my first time writing a classloader.

Thanks

sasdava at 2007-7-21 9:13:09 > top of Java-index,Java Essentials,Java Programming...
# 34

The trouble is you didn't print the name of the class being loaded the mistake was the getClass() when you are already looking at the class.

I think classes with a null classloader tend to be the ones which are loaded by the "primordial" class loader, classes like Object and Class which are actually hard coded into the JVM.

I had in mind something like:

public Class loadClass(String name) throws ClassNotFoundException {

Class c = super.loadClass(name);

ClassLoader cl = c.getClassLoader();

System.out.println("Loaded " + name + (cl == null ? " primordial " : cl == this ? " me" : " other");

return c;

}

malcolmmca at 2007-7-21 9:13:09 > top of Java-index,Java Essentials,Java Programming...
# 35

All right, the results are pretty much the same even if it's a little clearer now:

Loaded javax.swing.JFrame primordial

Loaded mbeanbrowser.MBeanBrowserMainWindow me

Loaded java.lang.Object primordial

Loaded javax.swing.tree.TreeNode primordial

Loaded mbeanbrowser.ServerBeanInstance me

Loaded mbeanbrowser.WebLogicServerInstance me

Loaded mbeanbrowser.WebSphereServerInstance me

Loaded javax.swing.tree.MutableTreeNode primordial

Loaded java.awt.Component primordial

Loaded java.awt.Container primordial

Loaded java.lang.Throwable primordial

Loaded java.io.IOException primordial

Loaded java.util.logging.Formatter primordial

Loaded java.util.logging.SimpleFormatter primordial

Loaded java.util.logging.Handler primordial

Loaded java.util.logging.FileHandler primordial

Loaded java.io.InputStream primordial

Loaded java.io.FileInputStream primordial

Loaded java.awt.event.ActionListener primordial

Loaded javax.swing.JButton primordial

Loaded javax.swing.JToolBar primordial

Loaded javax.swing.tree.TreeModel primordial

Loaded javax.swing.event.TreeSelectionListener primordial

Loaded javax.swing.JTree primordial

Loaded javax.swing.JScrollPane primordial

Loaded javax.swing.table.TableModel primordial

Loaded javax.swing.JTable primordial

Loaded javax.swing.JSplitPane primordial

Loaded java.awt.LayoutManager primordial

Loaded javax.swing.JLabel primordial

Loaded javax.swing.JPanel primordial

Loaded javax.swing.plaf.basic.BasicPanelUI primordial

Loaded com.sun.java.swing.plaf.windows.WindowsRootPaneUI primordial

Loaded java.util.logging.Logger primordial

Loaded java.util.Properties primordial

Loaded java.io.File primordial

Loaded java.lang.System primordial

Loaded com.sun.java.swing.plaf.windows.WindowsToolBarUI primordial

Loaded com.sun.java.swing.plaf.windows.WindowsBorders primordial

Loaded com.sun.java.swing.plaf.windows.WindowsButtonUI primordial

Loaded javax.swing.plaf.basic.BasicBorders primordial

Loaded mbeanbrowser.MBeanBrowserMainWindow$1 me

Loaded java.lang.Exception primordial

Loaded mbeanbrowser.MBeanBrowserMainWindow$2 me

Loaded mbeanbrowser.MBeanBrowserMainWindow$3 me

Loaded java.io.OutputStream primordial

Loaded java.io.FileOutputStream primordial

Loaded com.sun.java.swing.plaf.windows.WindowsSplitPaneUI primordial

Loaded javax.swing.tree.DefaultTreeModel primordial

Loaded javax.swing.tree.DefaultMutableTreeNode primordial

Loaded com.sun.java.swing.plaf.windows.WindowsTreeUI primordial

Loaded java.awt.Image primordial

Loaded java.util.List primordial

Loaded java.lang.String primordial

Loaded java.net.URL primordial

Loaded com.sun.java.swing.plaf.windows.WindowsLabelUI primordial

Loaded mbeanbrowser.MBeanBrowserMainWindow$BeanTreeSelectionListener me

Loaded javax.swing.plaf.basic.BasicViewportUI primordial

Loaded com.sun.java.swing.plaf.windows.WindowsScrollBarUI primordial

Loaded javax.swing.plaf.basic.BasicScrollPaneUI primordial

Loaded javax.swing.table.DefaultTableModel primordial

Loaded mbeanbrowser.BeanInfoTableModel me

Loaded java.io.Writer primordial

Loaded java.io.FileWriter primordial

Loaded java.util.Vector primordial

Loaded com.sun.java.swing.plaf.windows.WindowsTableHeaderUI primordial

Loaded javax.swing.plaf.basic.BasicTableUI primordial

Loaded java.awt.FlowLayout primordial

Loaded javax.swing.BorderFactory primordial

Loaded mbeanbrowser.ServerBeanInstance me

Loaded sun.io.CharToByteCp1252 primordial

Loaded sun.awt.windows.CharToByteWingDings primordial

Loaded sun.awt.CharToByteSymbol primordial

Loaded javax.swing.plaf.BorderUIResource primordial

Loaded mbeanbrowser.LoginPanel me

Loaded javax.swing.JComboBox primordial

Loaded javax.swing.JTextField primordial

Loaded javax.swing.JPasswordField primordial

Loaded java.awt.GridBagLayout primordial

Loaded java.awt.GridBagConstraints primordial

Loaded java.awt.Insets primordial

Loaded java.awt.event.ActionEvent primordial

Loaded javax.swing.JOptionPane primordial

java.lang.NoClassDefFoundError: javax/management/MBeanServer

at mbeanbrowser.MBeanBrowserMainWindow.login(MBeanBrowserMainWindow.java:191)

Loaded java.awt.Cursor primordial

at mbeanbrowser.MBeanBrowserMainWindow.access$200(MBeanBrowserMainWindow.java:54)

at mbeanbrowser.MBeanBrowserMainWindow$1.actionPerformed(MBeanBrowserMainWindow.java:107)

at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1786)

at javax.swing.AbstractButton$ForwardActionEvents.actionPerformed(AbstractButton.java:1839)

at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:420)

at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:258)

at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:245)

at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:231)

at java.awt.Component.processMouseEvent(Component.java:5100)

at java.awt.Component.processEvent(Component.java:4897)

at java.awt.Container.processEvent(Container.java:1569)

at java.awt.Component.dispatchEventImpl(Component.java:3615)

at java.awt.Container.dispatchEventImpl(Container.java:1627)

at java.awt.Component.dispatchEvent(Component.java:3477)

at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:3483)

at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3198)

at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3128)

at java.awt.Container.dispatchEventImpl(Container.java:1613)

at java.awt.Window.dispatchEventImpl(Window.java:1606)

at java.awt.Component.dispatchEvent(Component.java:3477)

at java.awt.EventQueue.dispatchEvent(EventQueue.java:480)

at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:201)

at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151)

at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:145)

at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:137)

at java.awt.EventDispatchThread.run(EventDispatchThread.java:100)

So, I guess that answers that question. The system classloader is still loading the majority of classes, especially the GUI classes. But the URLClassLoader (in the guise of JarClassLoader) is loading my classes, including:

MBeanBrowserMainWindow and all of its anonymous inner classes

ServerBeanInstance

WebLogicServerInstance

WebSphereServerInstance

In fact, ServerBeanInstance is loaded twice by JarClassLoader.

What does that tell us?

sasdava at 2007-7-21 9:13:09 > top of Java-index,Java Essentials,Java Programming...
# 36

AFAIKS that pretty much elimnates ClassLoader problems as a likely source of the bug.

You could try puting a log out both before and after the super.loadClass() so you can make absolutely sure it's that classloader that's trying, and failing to load MBeanServer, but I expect you'll find it is, since ServerBeanInstance is pointing at the right loader.

You could try extracting, and decompiling the MBeanServer.class file from the jar and making sure that, for example, the class is public.

Hang on a sec though. I didn't really check the URLs that the URLClassLoader is pointed at, but, given you adding a separater to the end I guess it's a directory. You do know you need a separate URL for each jar file to be accessed? Give it a directory and it expects unjarred class files. (When you've gone through the exotic it's time to check the obvious ;-) )

Have you run this stuff OK by putting everything on the class path?

Message was edited by:

malcolmmc

malcolmmca at 2007-7-21 9:13:09 > top of Java-index,Java Essentials,Java Programming...
# 37

The URLClassLoader in starter.Main is loading the GUI classes in a directory. The URLClassLoader in WebLogicServerInstance is loading classes from a jar file, weblogic.jar to be specific.

Everything works fine when it's all in the classpath, except that the javax.management classes interfere with each other, as I described earlier.

sasdava at 2007-7-21 9:13:09 > top of Java-index,Java Essentials,Java Programming...
# 38

Well, that could be the problem, I didn't realise you still had two classloaders active.

The classloader that loads your GUI components must be able to load classes from the weblogic.jar file too. So either you need to put both URLs into the one classloader or the GUI classloader needs to have the other as a parent, i.e the jar classloader needs to be set up first. Remember references can only go from a class' classloader to it's ancestors.

Incidentally you don't need to add a / to the end of directory paths - File.toURL should sort that out.

malcolmmca at 2007-7-21 9:13:09 > top of Java-index,Java Essentials,Java Programming...
# 39

The sound you are hearing is me banging my head on the desk.

I guess this takes us back to my original question, doesn't it. In my program if I select "WebLogic" from the JComboBox I want to load the classes located in weblogic.jar. If I select "WebSphere" I want to load the classes located in the other 19 jar files. I cannot put the 20 jar files in the classpath or put all 20 URL's into the constructor for one URLClassLoader because the javax.management classes interfere with each other.

So, am I stuck writing two versions of the same program or can I do this?

sasdava at 2007-7-21 9:13:09 > top of Java-index,Java Essentials,Java Programming...
# 40

You can still do it, but it means a more careful separation between the new runner package and the GUI package, specifically the runner package needs to make the selection before it invokes the "real" (i.e. weblogic using) classes. You might want. for example, to separate your JFrame from it's working contents. You'd open the JFrame, probably empty, ask for the selection, then load the browser part, passing it a reference to your JFrame which it then populates.

malcolmmca at 2007-7-21 9:13:09 > top of Java-index,Java Essentials,Java Programming...
# 41
I'm not sure that approach is feasible since the selection process is part of the GUI, but I'll work on it and see if I can make it work.
sasdava at 2007-7-21 9:13:09 > top of Java-index,Java Essentials,Java Programming...
# 42
I think maybe you need more view/model separation with a common view on two versions of the model.
malcolmmca at 2007-7-21 9:13:09 > top of Java-index,Java Essentials,Java Programming...
# 43

Whatever that means :)

I'm getting closer, I think. I'm bringing up the login screen before the main window comes up and it's connecting correctly. That's a MAJOR improvement.

I'm getting some new errors now but I'm not sure if the problem is my technique or the server I'm connecting to.

Unable to access I18n properties file, weblogic/i18n/i18n.properties: java.io.FileNotFoundException: Response: '404: Not Found' for url: 'http://10.11.12.238:7501/bea_wls_internal/classes/weblogic/i18n/i18n.properties'

java.lang.ExceptionInInitializerError

at weblogic.j2ee.ApplicationManager.loadClass(ApplicationManager.java:309)

at weblogic.j2ee.ApplicationManager.loadClass(ApplicationManager.java:258)

at weblogic.j2ee.ApplicationManager.loadClass(ApplicationManager.java:253)

at weblogic.j2ee.ApplicationManager.loadClass(ApplicationManager.java:216)

at weblogic.rmi.internal.ClientRuntimeDescriptor.computeInterfaces(ClientRuntimeDescriptor.java:239)

at weblogic.rmi.internal.ClientRuntimeDescriptor.intern(ClientRuntimeDescriptor.java:127)

at weblogic.rmi.internal.StubInfo.readObject(StubInfo.java:121)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

at java.lang.reflect.Method.invoke(Method.java:324)

at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:838)

etcetcetc

sasdava at 2007-7-21 9:13:09 > top of Java-index,Java Essentials,Java Programming...
# 44

> Whatever that means :)

It's called "loose coupling", dividing your classes between data handling and view components. Hopefully, then, you've class path complexities can be confined to the data classes.

Where you need two possible versions of a model class (in your case because they need different classloader setups to load them) you would peal of an interface, which both of them would implement, The interface can then be back on the classpath. So you need muck about with class loaders only when instaciating such an object and thereafter all access to it goes through the interface. You can create a "factory class" which instanciates all these variant classes according to the version you required. That confines all the classpath stuff to a single, static getInstance() method in an abstract ancestor of the factory class.

So wherever you'd currently use a new on one of the model classes you get the appropriate instance of the factory class and call a createXXX method on it, the object returned will be a concrete class in the appropriate environment, but you use it by casting it to an interface which is fully available.

You can even have both sets of classes going at the same time (it's permissiable to have two classes with the same FQN loaded if they aren't on the same line of descent in the classloader tree).

I don't know enough about WebLogic and the way you are using it to be certain such separation is practical but I would think it should be.

If you use an IDE like Netbeans there are facilities for automatically generating an interface which defines all the methods of an existing class.

>

> Unable to access I18n properties file,

> weblogic/i18n/i18n.properties:

> java.io.FileNotFoundException: Response: '404: Not

> Found' for url:

> 'http://10.11.12.238:7501/bea_wls_internal/classes/web

> logic/i18n/i18n.properties'

>

Now that has to be an error in your WebLogic server setup. It's a failure to connect to a server, probably not a program problem at all.

malcolmmca at 2007-7-21 9:13:09 > top of Java-index,Java Essentials,Java Programming...
# 45
No, it's definately a program problem. My Weblogic only version of the program connects without a problem.The weblogic/i18n/i18n.properties object is in the weblogic.jar file, so that leaves the question, can URLClassLoader load a resource other than a class out of a local jar?
sasdava at 2007-7-21 9:13:14 > top of Java-index,Java Essentials,Java Programming...
# 46

Sure it can. In fact that's one of the scenarios that made me suggest setting the context classloader, but it depends how the class that loads the resource requests it. If it uses getClass().getResource() then it will use the classloader that loaded the class doing the loading.

However the error message you got exhibited a domain:port format which points to a connection, rather than a resource within the class heirarchy.

Of course it may have the wrong domain due to not reading the right .properties file. It looks like the sort of thing you may have to configure.

malcolmmca at 2007-7-21 9:13:14 > top of Java-index,Java Essentials,Java Programming...
# 47

I would suppose that this would be easy to implement as three applications...

1. The GUI

2. App to talk to websphere

3. App to talk to weblogic

The GUI uses sockets to talk to the two apps. The GUI can even launch the two apps. The two apps talk to the respective J2EE container. All that is needed is an interface to each. Each can be tested seperately. No classloaders are needed at all.

It even easily supports adding yet another J2EE container.

jschella at 2007-7-21 9:13:14 > top of Java-index,Java Essentials,Java Programming...
# 48
Just for the sake of curiosity, how would the GUI application invoke the others? Using Runtime?
sasdava at 2007-7-21 9:13:14 > top of Java-index,Java Essentials,Java Programming...
# 49

> Just for the sake of curiosity, how would the GUI

> application invoke the others? Using Runtime?

Yep.

Or you could just install them as a service on the box as well.

Technically you could just install them as servers too. Then only one install would be needed. You could even just do one that way because then the other j2ee could be accessed directly in the gui.

jschella at 2007-7-21 9:13:14 > top of Java-index,Java Essentials,Java Programming...
# 50
Installing as services? Wouldn't that do away with crossplatform?
sasdava at 2007-7-21 9:13:14 > top of Java-index,Java Essentials,Java Programming...
# 51
> Installing as services? Wouldn't that do away with> crossplatform?Huh?You can run a cron job on a unix box - it serves the same purpose in that the GUI would then not have to explicitly start it.
jschella at 2007-7-21 9:13:14 > top of Java-index,Java Essentials,Java Programming...
# 52
That may be a little complex for something that's supposed to be a fairly simple diagnostic tool.
sasdava at 2007-7-21 9:13:14 > top of Java-index,Java Essentials,Java Programming...