schwarz
schwarz

Reputation: 521

Class defined in another plugin cannot be found by the main plugin - Eclipse Product

I exported my plugin project as a Product and when I run the product (eclipse application), the main plugin (org.example.framework.core) cannot find a class defined in another plugin (org.example.abc) which implements an extension to an extension point provided by the main plugin. The class is one of the elements defined in the extension. However, when I run the project in Eclipse, everything runs fine!

Here is the log (atvste.ppt.ptfwDescription.abc.decoderInfo is a package in org.example.abc plugin):

0 [Worker-2] ERROR org.example.framework.core.ptfw.codec.decode.MsgDecoderInfo org.example.framework.core.ptfw.codec.decode.MsgDecoderInfo.createInstance(MsgDecoderInfo.java:114) : can not create class for :atvste.ppt.ptfwDescription.abc.decoderInfo.MsgDecoderInfoABC atvste.ppt.ptfwDescription.abc.decoderInfo.MsgDecoderInfoABC cannot be found by org.example.framework.core_1.0.0.201404111439 java.lang.ClassNotFoundException: atvste.ppt.ptfwDescription.abc.decoderInfo.MsgDecoderInfoABC cannot be found by org.example.framework.core_1.0.0.201404111439 at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:501) at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:421) at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:412) at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:107) at java.lang.ClassLoader.loadClass(Unknown Source) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Unknown Source) at org.example.framework.core.ptfw.codec.decode.MsgDecoderInfo.createInstance(MsgDecoderInfo.java:104) at org.example.framework.core.ptfw.codec.decode.DecoderInfo.<init>(DecoderInfo.java:56) at org.example.framework.core.ptfw.codec.decode.DecoderInfo.createInstance(DecoderInfo.java:125) at org.example.framework.core.ptfw.codec.ptfwObjectsFactory.decoderInfoItf_createInstance(ptfwObjectsFactory.java:200) at org.example.framework.persistence.jaxb.ptfwDescriptionPersistenceJaxb.createptfwDescription(ptfwDescriptionPersistenceJaxb.java:326) at org.example.framework.persistence.jaxb.ptfwDescriptionPersistenceJaxb.fillptfwDescription(ptfwDescriptionPersistenceJaxb.java:247) at org.example.framework.persistence.jaxb.ptfwDescriptionPersistenceJaxb.createInstance(ptfwDescriptionPersistenceJaxb.java:232) at org.example.framework.persistence.jaxb.ptfwDescriptionPersistenceJaxb.open(ptfwDescriptionPersistenceJaxb.java:146) at org.example.framework.core.ptfw.codec.ptfwDescription.createInstance(ptfwDescription.java:152) at org.example.framework.core.ptfw.codec.command.CmdLoadptfwDescription.loadptfwDescription(CmdLoadptfwDescription.java:50) at org.example.framework.core.ptfw.codec.command.CmdLoadptfwDescription.execute(CmdLoadptfwDescription.java:40) at org.example.framework.core.runtime.JobService$2.run(JobService.java:93) at org.eclipse.core.internal.jobs.Worker.run(Worker.java:53)

EDIT: Function for creating instance of the class not found

 public static IMessageDecoderInfo createInstance(XmlgMsgDecoderInfo pMsgDecoderInfoType,
        IMessageDecoderInfo msgDecoder)
{

    String className = pMsgDecoderInfoType.getClassName();
    if(className!=null)
    {
        try
        {
            Class<?> formalArgs[] = new Class[1];
            formalArgs[0] = XmlgMsgDecoderInfo.class;
            Class<?> clazz;
            if (msgDecoder != null)
            {
                clazz = msgDecoder.getClass();
            }
            else
            {
                clazz = Class.forName( className );
            }
            Constructor<?> constructor = clazz.getConstructor(formalArgs);
            java.lang.Object  actualArgs[] =
            { pMsgDecoderInfoType };

            return (IMessageDecoderInfo)constructor.newInstance(actualArgs);
        }catch(Exception e) {
            String error = "can not create class for :" +className+ " " + e.getMessage();
            if (LOGGER.isEnabledFor(Level.ERROR)) {
                LOGGER.error(error, e);
            }
            throw new CreatePtfwElementRuntimeException(error, e);
        }
    }
    return new MsgDecoderInfo(pMsgDecoderInfoType);
}`

Upvotes: 2

Views: 1563

Answers (1)

greg-449
greg-449

Reputation: 111142

Because of the complex class loader system used by Eclipse you cannot use Class.forName to load a class in another plugin.

If your code is processing an extension point definition you will have the IConfigurationElement for the configuration element that specifies the class name. You can use

IConfigurationElement configElement = ....;

Object classInstance = configElement.createExecutableExtension("class attribute name");

where 'class attribute name' is the name of the attribute in the extension point element that specifies the class to load. The class being created must have a no argument constructor.

Alternatively you can load a class using:

Bundle bundle = Platform.getBundle("plugin id");

Class<?> theClass = bundle.loadClass("class name");

... construct as usual ...

If you have the IConfigurationElement you can get the plugin id using

String pluginId = configElement.getContributor().getName();

Upvotes: 3

Related Questions