Insubstantial doesn't load via custom classloader #99

Closed
bobbylight opened this Issue Oct 27, 2012 · 4 comments

Projects

None yet

4 participants

@bobbylight

My application uses a separate URLClassLoader to handle dynamically identifying and installing extra LookAndFeels. The actual install of the new LookAndFeel would take effect on application restart. When trying to use Insubstantial 7.1 or 7.2, I get the following stack trace:

Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: No interpolator found for java.lang.Float:java.lang.Float
at org.pushingpixels.trident.TimelinePropertyBuilder.getFieldInfo(TimelinePropertyBuilder.java:259)
at org.pushingpixels.trident.Timeline.addPropertyToInterpolate(Timeline.java:355)
at org.pushingpixels.trident.Timeline.addPropertyToInterpolate(Timeline.java:365)
at org.pushingpixels.substance.internal.animation.StateTransitionTracker.onModelStateChanged(StateTransitionTracker.java:402)
at org.pushingpixels.substance.internal.animation.StateTransitionTracker$4.stateChanged(StateTransitionTracker.java:264)
at javax.swing.DefaultButtonModel.fireStateChanged(DefaultButtonModel.java:349)
at javax.swing.DefaultButtonModel.setEnabled(DefaultButtonModel.java:209)
at javax.swing.AbstractButton.setEnabled(AbstractButton.java:2088)
at javax.swing.JMenuItem.setEnabled(JMenuItem.java:311)
at javax.swing.AbstractAction.setEnabledFromAction(AbstractAction.java:102)
at javax.swing.AbstractButton.actionPropertyChanged(AbstractButton.java:1216)
at javax.swing.JMenuItem.actionPropertyChanged(JMenuItem.java:410)
at javax.swing.AbstractButton$ButtonActionPropertyChangeListener.actionPropertyChanged(AbstractButton.java:1361)
at javax.swing.AbstractButton$ButtonActionPropertyChangeListener.actionPropertyChanged(AbstractButton.java:1350)
at javax.swing.ActionPropertyChangeListener.propertyChange(ActionPropertyChangeListener.java:88)
at java.beans.PropertyChangeSupport.fire(PropertyChangeSupport.java:335)
at java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:327)
at javax.swing.event.SwingPropertyChangeSupport.firePropertyChange(SwingPropertyChangeSupport.java:92)
at java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:263)
at javax.swing.AbstractAction.firePropertyChange(AbstractAction.java:276)
at javax.swing.AbstractAction.setEnabled(AbstractAction.java:236)
at org.pushingpixels.substance.internal.utils.SubstanceTitlePane.setState(SubstanceTitlePane.java:1088)
at org.pushingpixels.substance.internal.utils.SubstanceTitlePane.setState(SubstanceTitlePane.java:1002)
at org.pushingpixels.substance.internal.utils.SubstanceTitlePane.addNotify(SubstanceTitlePane.java:653)
at java.awt.Container.addNotify(Container.java:2769)
at javax.swing.JComponent.addNotify(JComponent.java:4743)
at java.awt.Container.addNotify(Container.java:2769)
at javax.swing.JComponent.addNotify(JComponent.java:4743)
at javax.swing.JRootPane.addNotify(JRootPane.java:756)
at java.awt.Container.addNotify(Container.java:2769)
at java.awt.Window.addNotify(Window.java:769)
at java.awt.Frame.addNotify(Frame.java:487)
at java.awt.Window.pack(Window.java:806)
at org.fife.rtext.RText.setIconGroupByName(RText.java:1256)
at org.fife.rtext.RText.preToolBarInit(RText.java:1074)
at org.fife.ui.app.AbstractGUIApplication$StartupRunnable.run(AbstractGUIApplication.java:1375)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:705)
at java.awt.EventQueue.access$000(EventQueue.java:101)
at java.awt.EventQueue$3.run(EventQueue.java:666)
at java.awt.EventQueue$3.run(EventQueue.java:664)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:675)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:211)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

If I put all substance/trident jars on the main application classpath, everything works fine (probably just the one with interpolators is all that matters).

This prevents folks like me from having applications that dynamically load LookAndFeels from using Insubstantial. We have to have hard dependencies in place.

IIRC, I had to fix at least one ClassLoader issue with the "original" Substance builds myself to get something like this working, but that little experience was long-since thrown away. :(

@shemnon
Member
shemnon commented Nov 1, 2012

It looks to me trident is using the thread context class loader to load some of the interpolators it uses (https://github.com/Insubstantial/insubstantial/blob/master/trident/src/main/java/org/pushingpixels/trident/TridentConfig.java#L82). If I were to add a system property that said "Use the getClass().getClassLaoder()" instead would that work? Or does each jar get it's own classloader?

@kschaefe
kschaefe commented Nov 1, 2012

Not sure if this is going to be 100% on point, but this is the code I use in the SwingX LookAndFeelAddons class for obtaining the correct ClassLoader:

private static ClassLoader getClassLoader() {
    ClassLoader cl = null;

    try {
        cl = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
            @Override
            public ClassLoader run() {
                return LookAndFeelAddons.class.getClassLoader();
            }
        });
    } catch (SecurityException ignore) { }

    if (cl == null) {
        final Thread t = Thread.currentThread();

        try {
            cl = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
                @Override
                public ClassLoader run() {
                    return t.getContextClassLoader();
                }
            });
        } catch (SecurityException ignore) { }
    }

    if (cl == null) {
        try {
            cl = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
                @Override
                public ClassLoader run() {
                    return ClassLoader.getSystemClassLoader();
                }
            });
        } catch (SecurityException ignore) { }
    }

    return cl;
}
@bobbylight

@shemnon, I think that would work (the system property idea you suggested). I'll try doing a custom build myself to see if it works my specific case. Never used gradle before, wish me luck!

@shemnon shemnon added a commit that closed this issue Nov 6, 2012
@shemnon shemnon fix #99 - start looking at the class classloader before going to the …
…thread context class loader.
02af760
@shemnon shemnon closed this in 02af760 Nov 6, 2012
@shemnon shemnon added a commit that referenced this issue Nov 6, 2012
@shemnon shemnon fix #99 - classloader tweak f48d5a9
@Dim8
Dim8 commented Oct 8, 2016

Still getting the error. Yet, it turned out I was missing the trident-plugin.properties. More info in SO.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment