Question

I would like to marshall Java objects into XML and vice-versa from within an Unsigned Applet and I can't change any of the security permission/policy files, or sign the application.

I seem to get a Security exception, because JAXB is attempting to access fields or constructors that it can't in the applet sandbox.

The browser is running JRE 1.6.0_17

I'm also open to solutions based on some other XML (or JSON) library but have tried the following and pretty much run into a similar problem; - XStream - Gson

Given (something like) the following object:

@XmlType
@XmlRootElement
public class SimpleObject {

    public String sampleText;

    public SimpleObject() {
    }

    public String getSampleText() {
        return sampleText;
    }

    public void setSampleText(String sampleText) {
        this.sampleText = sampleText;
    }
}

And the following simple JAXB code:

public void actionPerformed(ActionEvent e) {
    try {
        JAXBContext jc = JAXBContext.newInstance(SimpleObject.class);
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        SimpleObject object = new SimpleObject();
        object.setSampleText("Hello");

        marshaller.marshal(object, System.out);
    }
    catch (JAXBException e1) {
        throw new RuntimeException(e1);
    }
}

I get the following exception:

Exception in thread "AWT-EventQueue-2" java.security.AccessControlException: access denied (java.lang.RuntimePermission accessDeclaredMembers)
    at java.security.AccessControlContext.checkPermission(Unknown Source)
    at java.security.AccessController.checkPermission(Unknown Source)
    at java.lang.SecurityManager.checkPermission(Unknown Source)
    at java.lang.SecurityManager.checkMemberAccess(Unknown Source)
    at java.lang.Class.checkMemberAccess(Unknown Source)
    at java.lang.Class.getDeclaredConstructor(Unknown Source)
    at com.sun.xml.internal.bind.v2.model.nav.ReflectionNavigator.hasDefaultConstructor(Unknown Source)
    at com.sun.xml.internal.bind.v2.model.nav.ReflectionNavigator.hasDefaultConstructor(Unknown Source)
    at com.sun.xml.internal.bind.v2.model.impl.ClassInfoImpl.<init>(Unknown Source)
    at com.sun.xml.internal.bind.v2.model.impl.RuntimeClassInfoImpl.<init>(Unknown Source)
    at com.sun.xml.internal.bind.v2.model.impl.RuntimeModelBuilder.createClassInfo(Unknown Source)
    at com.sun.xml.internal.bind.v2.model.impl.RuntimeModelBuilder.createClassInfo(Unknown Source)
    at com.sun.xml.internal.bind.v2.model.impl.ModelBuilder.getClassInfo(Unknown Source)
    at com.sun.xml.internal.bind.v2.model.impl.RuntimeModelBuilder.getClassInfo(Unknown Source)
    at com.sun.xml.internal.bind.v2.model.impl.RuntimeModelBuilder.getClassInfo(Unknown Source)
    at com.sun.xml.internal.bind.v2.model.impl.ModelBuilder.getClassInfo(Unknown Source)
    at com.sun.xml.internal.bind.v2.model.impl.RuntimeModelBuilder.getClassInfo(Unknown Source)
    at com.sun.xml.internal.bind.v2.model.impl.RuntimeModelBuilder.getClassInfo(Unknown Source)
    at com.sun.xml.internal.bind.v2.model.impl.ModelBuilder.getTypeInfo(Unknown Source)
    at com.sun.xml.internal.bind.v2.model.impl.ModelBuilder.getTypeInfo(Unknown Source)
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(Unknown Source)
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(Unknown Source)
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(Unknown Source)
    at com.sun.xml.internal.bind.v2.ContextFactory.createContext(Unknown Source)
    at com.sun.xml.internal.bind.v2.ContextFactory.createContext(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at javax.xml.bind.ContextFinder.newInstance(Unknown Source)
    at javax.xml.bind.ContextFinder.find(Unknown Source)
    at javax.xml.bind.JAXBContext.newInstance(Unknown Source)
    at javax.xml.bind.JAXBContext.newInstance(Unknown Source)
    at nz.co.zeal.maker.application.actions.build.JAXBTestAction.actionPerformed(JAXBTestAction.java:24)
    at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
    at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
    at javax.swing.AbstractButton.doClick(Unknown Source)
    at javax.swing.plaf.basic.BasicMenuItemUI.doClick(Unknown Source)
    at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(Unknown Source)
    at java.awt.Component.processMouseEvent(Unknown Source)
    at javax.swing.JComponent.processMouseEvent(Unknown Source)
    at java.awt.Component.processEvent(Unknown Source)
    at java.awt.Container.processEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)
Was it helpful?

Solution

I never did quite figure this one out. What I did instead was to grab a fairly simple JSON library called Flexjson. It also threw a similar security exception but the library was simple enough that I was able to switch-off the library code that causes the exception in an Applet with a boolean flag.

OTHER TIPS

I also tried to find a solution with JAXB without any success.

I switched to Axis2 (1.5.4) with ADB binding, but it also tried accessing system properties which failed with security manager checks.

In the end, I got a workable solution together by using AspectJ and using an aspect that rewrites System.getProperty() calls to return null when they fail. Since all the properties Axis2 needed were non-critical anyway this worked. I also needed to apply an aspect over org.apache.axiom.util.stax.dialect.StAXDialectDetector.getRootUrlForResource() to always return null since it tried to make a ClassLoader.getSystemClassLoader() call which also failed under a security manager. Again this seemed like a non-critical call. Got AspectJ to rewrite the Axis2 classes at build-time and it ran as an unsigned applet.

It's a really messy solution, but at least it worked.

I couldn't get the same AspectJ hack working with JAXB because JAXB requires direct access to the private fields of classes which doesn't fly under a security manager if JAXB is bundled with the applet (which we need to do if AspectJ is used to rewrite classes).

This may solve your problem. I know it solved mine :)

public void actionPerformed(ActionEvent e) {
    try {
    JAXBContext jc = AccessController.doPrivileged(new PrivilegedExceptionAction<JAXBContext>() {

        public JAXBContext run() throws JAXBException {

            // needs to run here otherwise throws AccessControlException
            return JAXBContext.newInstance(SimpleObject.class);
        }
    });         
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        SimpleObject object = new SimpleObject();
        object.setSampleText("Hello");

        marshaller.marshal(object, System.out);
    }
    catch (JAXBException e1) {
        throw new RuntimeException(e1);
    }
    } catch (PrivilegedActionException e2) {
    throw new RuntimeException(e2);
    }
}

Hope it helps

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top