Menu

#10 Operation not sending paramaters

open
nobody
None
5
2002-11-25
2002-11-25
Jose M. Rus
No

PRODUCT VERSION
MC4J Application 1.1

OPERATING SYSTEM
Linux Mandrake 8.1

DESCRIPTION
When a operation of a MBean is invoked with a parameter
of a custom class (defined with a property editor) the
value of the parameter sended to the MBeanServer is null.

REPRODUCIBILITY
Always

STEPS TO REPRODUCE
Consider the following MBean with a single operation
that has a paremeter that wraps a String instance:

<file>
package test;

public interface ComponentMBean {
public ComponentData operation(ComponentData data);
}
</file>

<file>
package test;

import java.io.Serializable;

public class ComponentData implements Serializable {

protected String data;

public ComponentData(String data) {
this.data = data;
}

public void setData(String data) {
this.data = data;
}

public String toString() {
return data;
}
}
</file>

<file>
package test;

public class Component implements ComponentMBean {

public ComponentData operation(ComponentData data) {
if (data == null) {
System.out.println("ComponentData is null");
return new ComponentData("null?");
} else {
return new ComponentData("<" +
data.toString() + ">");
}
}
}
</file>

The following property editor limits the value of
ComponentData instances to three tagged values:

<file>
package test;

import java.beans.*;
import java.awt.Rectangle;
import java.awt.Graphics;

public class ComponentDataEditor extends
PropertyEditorSupport {

protected static final String DEFAULT = "Red";

protected ComponentData data;

public String[] getTags() {
return new String[] { "Red", "Square", "Pretty" };
}

public String getAsText() {
if (data == null) {
data = new ComponentData(DEFAULT);
}
System.out.println(data.toString() + "
getAsText()");
return data.toString();
}

public java.awt.Component getCustomEditor() {
return null;
}

public String getJavaInitializationString() {

System.out.println("getJavaInitializationString()");
return "new Component()";
}

public Object getValue() {
if (data == null) {
data = new ComponentData(DEFAULT);
}
System.out.println(data.toString() + "
getValue()");
return data;
}

public boolean isPaintable() {
return false;
}

public void paintValue(Graphics graphics, Rectangle
rectangle) { }

public void setAsText(String str) throws
IllegalArgumentException {
System.out.println("setAsText(" + str + ")");
if (data == null) {
data = new ComponentData((str == null) ?
DEFAULT : str);
} else {
data.setData((str == null) ? DEFAULT : str);
}
}

public void setValue(Object obj) {
System.out.println("setValue(" + obj+ ")");
if (data == null) {
data = new ComponentData((obj == null) ?
DEFAULT : obj.toString());
} else {
data.setData((obj == null) ? DEFAULT :
obj.toString());
}
}

public boolean supportsCustomEditor() {
return false;
}
}
</file>

Now the following class starts the MX4J MBeanServer
with the JRMP connector. It tests that the JRMP
connector blunded with MX4J sends and receives
correctly the parameter of ComponentBean.operation().

<file>
package test;

import javax.naming.*;
import javax.management.*;
import mx4j.adaptor.http.*;
import mx4j.server.interceptor.*;
import mx4j.tools.naming.*;
import mx4j.adaptor.rmi.jrmp.*;
import mx4j.connector.*;
import mx4j.connector.rmi.jrmp.*;
import java.io.IOException;

public class Main {

public static void main(String[] args) {
try {
MBeanServer server =
MBeanServerFactory.createMBeanServer();

/* Create the MBean */
ObjectName componentName = new
ObjectName(":mbean=Component");
server.createMBean("test.Component",
componentName, null,
null, null);

/* Prepare JRMP */
NamingService namingService = new
NamingService();
server.registerMBean(namingService,
new ObjectName("Naming:type=rmiregistry"));
namingService.start();
JRMPAdaptor jrmpAdaptor = new JRMPAdaptor();
server.registerMBean(jrmpAdaptor,
new ObjectName("Adaptor:protocol=JRMP"));
jrmpAdaptor.setJNDIName("jrmp");

System.setProperty(Context.INITIAL_CONTEXT_FACTORY,

"com.sun.jndi.rmi.registry.RegistryContextFactory");
System.setProperty(Context.PROVIDER_URL,
"rmi://localhost:1099");
jrmpAdaptor.start();

/* Test that the JRMP connector handles
parameters correctly */
JRMPConnector connector = new JRMPConnector();
connector.connect("jrmp", null);
RemoteMBeanServer remoteServer =
connector.getRemoteMBeanServer();
Object result =
remoteServer.invoke(componentName, "operation",
new Object[] { new ComponentData("A
test") },
new String[] {
ComponentData.class.getName() });
assert ("<A test>".equals(result));

/* OK, Server started */
System.out.println ("MBean Server ready.");

} catch (JMException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
} catch (NamingException ex) {
ex.printStackTrace();
}
}
}
</file>

To reproduce the bug:
* Compile the source code (included as attachment).
* Make a .jar file and copy it to the mc4j/lib
directory.
* Run the Main class and wait for the "MBean Server
ready" message. The correct behaviour of the MX4J has
then been tested.
* Connect the MC4J Management Console to he MBean
Server.
* Execute the ComponentMBean.operation(). The MBean
is exposed and a combo box shows the allowed values for
the parameter, but when the operation is invoked the
component in the MX4J Server receives a null (a warning
is printed is System.out).

Discussion

  • Jose M. Rus

    Jose M. Rus - 2002-11-25
     
  • James Wilson

    James Wilson - 2003-07-29

    Logged In: YES
    user_id=449959

    changing the Bean class from implementing the ___MBean
    interface to the DynamicMBean interface will fix the issue.
    Though only if the full MBeanInfo class is constructed
    without using the reflection classes.

    This does seem like a bug. As it would be much easier to
    not have to rely on the MBeanInfo class to define the operation.

    I see this as a duplicate of 622242. Or is that one a
    duplicate of this bug <grin/>

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.