Running BIRT reports which are based on model objects in a separate plugin cause ClassNotFoundException

StackOverflow https://stackoverflow.com/questions/21777485

質問

I am developing an eclipse Rich Client application which contains a model plugin and a report plugin. Reports in the report plugin access the model via a data access class in the model plugin. The model objects are persisted to the file system using XMLEncoder.

In the report plugin a report tries to access a model object via the data access class but a ClassNotFoundException is thrown.

I debugged the report and I can see that, although the BIRT classloader is initially active, when the files are deserialised the eclipse.osi default classloader is being used.

What do I need to do in order to be able to load the classes?

JS in BIRT

importPackage(Packages.com.acme.model.dao);
model = new Packages.com.acme.model.dao.AtfObjects();
list = model.getProtocols(path);

AtfObjects

public static List<Protocol> getProtocols(String path) throws Exception
{
    List<Protocol> result = new ArrayList<Protocol>();

    File file = new File(path);
    if (file.exists())
    {
        String xml = FileUtils.read(file);

        try
        {
            Trace.out("P1");
            Protocol pp = new Protocol();  // <-- this works
            Trace.out("Class: %s", pp.getClass().getName());
            Trace.out("ClassLoader: %s", pp.getClass().getClassLoader());
            Trace.out("Deserialise %s", file);
            Class c = Class.forName("com.acme.model.Protocol");
            Object o = c.newInstance();  // <-- this works
            XMLSerializer xs = new XMLSerializer();
            Protocol p = xs.deserialize(xml, Protocol.class); // <-- this fails
            result.add(p);
        }
        catch (Exception e)
        {
        }
    }

    return result;
}


@Override
public Object deserialize(String xml) throws SerializationException
{
    XMLDecoder decoder = null;
    InputStream in = null;

    try
    {
        in = new ByteArrayInputStream(xml.getBytes("UTF-8"));
        decoder = new XMLDecoder(in);
        Object object = (Object) decoder.readObject();  // <-- ClassNotFound Protocol
        decoder.close();

        return object;
    }
    catch (Exception e)
    {
        throw new SerializationException(e);
    }
役に立ちましたか?

解決

I'm not sure how good this solution is. It avoids the ClassNotFoundException when debugging but it remains to be seen how well it works when the report is used from within the application at runtime.

public static List<Protocol> getProtocols(String path) throws Exception
{
    List<Protocol> result = new ArrayList<Protocol>();
    File file = new File(path);
    if (file.exists())
    {
        String xml = FileUtils.read(file);

        try
        {
            Trace.out("P1");
            Protocol pp = new Protocol();
            Trace.out("Class: %s", pp.getClass().getName());
            Trace.out("ClassLoader: %s", pp.getClass().getClassLoader());

            // FORCE THREAD CLASSLOADER
            Thread.currentThread().setContextClassLoader(
                    pp.getClass().getClassLoader());
            XMLSerializer xs = new XMLSerializer();
            Protocol p = xs.deserialize(xml, Protocol.class);
            result.add(p);
        }
        catch (Exception e)
        {
        }
    }

    return result;
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top