Understanding Maven-built Bundles and NoClassDefFoundErrors

432 views
Skip to first unread message

michael...@non.agilent.com

unread,
Jul 11, 2014, 2:39:56 PM7/11/14
to cytoscape...@googlegroups.com, anya_t...@agilent.com

I'm still having trouble building a bundle app to work appropriately. When our bundle app runs, following a certain execution branch gets a NoClassDefFoundError for the java class (javax.net.ssl.SSLSocketFactory) (see below). Our bundle app (ENViz) uses ftp4j (a 3rd party library) which uses javax.net.ssl.SSLSocketFactory. To include ftp4j in our app, I made a simple wrapper using mvn install:install-file. To resolve import packages for our bundle, I used the maven-bundle-plugin using:

 

<Import-Package>*;resolution:=optional</Import-Package>

 

I'm also using the maven-shade-plugin to package up the extra, non bundle libraries our app uses.

 

So why is the javax class not available to link to when running? What should I do to fix this and avoid it in the future? Thanks!

 

Error

java.lang.NoClassDefFoundError: javax/net/ssl/SSLSocketFactory

        at it.sauronsoftware.ftp4j.FTPClient.<init>(FTPClient.java:178)

        at com.agilent.labs.enviz.utils.InternetDataDownloader.configFTP(InternetDataDownloader.java:349)

        at com.agilent.labs.enviz.utils.InternetDataDownloader.performFTPDownload(InternetDataDownloader.java:201)

        at com.agilent.labs.enviz.utils.InternetDataDownloader.downloadURLContent(InternetDataDownloader.java:188)

        at com.agilent.labs.enviz.utils.InternetDataDownloader.ensureLocalUpdatedData(InternetDataDownloader.java:115)

        at com.agilent.labs.enviz.visualization.go.InternetNCBIGODataDataDownloader.<init>(InternetNCBIGODataDataDownloader.java:41)

        at com.agilent.labs.enviz.visualization.go.GeneGOData$Gene2GoDataReader.<init>(GeneGOData.java:276)

        at com.agilent.labs.enviz.visualization.go.GeneGOData$Gene2GoDataReader.<init>(GeneGOData.java:243)

        at com.agilent.labs.enviz.visualization.go.GeneGOData.basicReadData(GeneGOData.java:126)

        at com.agilent.labs.enviz.visualization.go.GeneGOData.readData(GeneGOData.java:97)

        at com.agilent.labs.enviz.visualization.go.CreateGOAnnotationsTask.run(CreateGOAnnotationsTask.java:126)

        at org.cytoscape.work.internal.task.JDialogTaskManager$TaskRunnable.innerRun(JDialogTaskManager.java:321)

        at org.cytoscape.work.internal.task.JDialogTaskManager$TaskRunnable.run(JDialogTaskManager.java:350)

        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)

        at java.util.concurrent.FutureTask.run(FutureTask.java:262)

        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)

        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)

        at java.lang.Thread.run(Thread.java:744)

Caused by: java.lang.ClassNotFoundException: javax.net.ssl.SSLSocketFactory not found by com.agilent.labs.enviz.ENViz [170]

        at org.apache.felix.framework.ModuleImpl.findClassOrResourceByDelegation(ModuleImpl.java:812)

        at org.apache.felix.framework.ModuleImpl.access$400(ModuleImpl.java:72)

        at org.apache.felix.framework.ModuleImpl$ModuleClassLoader.loadClass(ModuleImpl.java:1807)

        at java.lang.ClassLoader.loadClass(ClassLoader.java:358)

        ... 18 more

Tim Hull

unread,
Jul 14, 2014, 12:48:22 PM7/14/14
to cytoscape...@googlegroups.com
If you packaged ftp4j as a bundle, it will have to import its dependencies in the same way as your main bundle. So I would either try doing that, or perhaps embedding the code in your JAR without trying to turn it into a bundle (i.e. using maven-shade-plugin)...

Tim


--
You received this message because you are subscribed to the Google Groups "cytoscape-helpdesk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cytoscape-helpd...@googlegroups.com.
To post to this group, send email to cytoscape...@googlegroups.com.
Visit this group at http://groups.google.com/group/cytoscape-helpdesk.
For more options, visit https://groups.google.com/d/optout.

michael...@non.agilent.com

unread,
Jul 14, 2014, 1:11:44 PM7/14/14
to cytoscape...@googlegroups.com

Thanks Tim. We just used mvn install:install-file to put ftp4j in the local repository. That's not a bundle, is it? The other strange thing is that the dependency is just standard java classes which we've never had to specify for other import packages.

Tim Hull

unread,
Jul 14, 2014, 1:15:08 PM7/14/14
to cytoscape...@googlegroups.com
If you use maven-bundle-plugin's Embed Dependencies feature and specify something as a Maven dependency, it will try to make it into a bundle. That's where I suspect things are going wrong, as ftp4j isn't a true Mavenized JAR...

Tim

michael...@non.agilent.com

unread,
Jul 14, 2014, 1:45:06 PM7/14/14
to cytoscape...@googlegroups.com

We don't use Embed Dependencies. Here's the maven-bundle-plugin and maven-shade-plugin instructions we use:

 

                    <plugin>

                           <groupId>org.apache.felix</groupId>

                           <artifactId>maven-bundle-plugin</artifactId>

                           <version>2.3.7</version>

                           <extensions>true</extensions>

                           <configuration>

                                 <instructions>

                                        <Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>

                                        <Bundle-Version>${project.version}</Bundle-Version>

                                        <Private-Package>${bundle.namespace}.*,org.cytoscape.utils</Private-Package>

                                        <Export-Package>!${bundle.namespace}.*,!org.cytoscape.utils</Export-Package>

                                        <Bundle-Activator>${bundle.namespace}.${project.artifactId}</Bundle-Activator>

                                        <Cytoscape-API-Compatibility>${cytoscape.api.version}</Cytoscape-API-Compatibility>

                                        <Import-Package>*;resolution:=optional</Import-Package>

                                 </instructions>

                           </configuration>

                    </plugin>

                    <!-- Build a jar containing all the ENViz dependencies: -->

                    <plugin>

                           <groupId>org.apache.maven.plugins</groupId>

                           <artifactId>maven-shade-plugin</artifactId>

                           <version>2.3</version>

                           <executions>

                                 <execution>

                                        <phase>package</phase>

                                        <goals>

                                               <goal>shade</goal>

                                        </goals>

                                 </execution>

                           </executions>

                           <configuration>

                              <filters>

                                 <filter>

                                 <artifact>*:*</artifact>

                                        <excludes>

                                        <exclude>META-INF/*.SF</exclude>

                                        <exclude>META-INF/*.DSA</exclude>

                                        <exclude>META-INF/*.RSA</exclude>

                                        </excludes>

                           </filter>

                           </filters>                      

                    </configuration>        

                    </plugin>

With a dependency on ftp4j of:

             <dependency>

                    <groupId>it.sauronsoftware</groupId>

                    <artifactId>ftp4j</artifactId>

                    <version>1.7.2</version>

             </dependency>

 

Is there anything obviously wrong with this?

Tim Hull

unread,
Jul 14, 2014, 1:57:05 PM7/14/14
to cytoscape...@googlegroups.com
That's likely your issue - in general, if you're building a bundle plugin with embedded dependencies using Maven, you should use Embed-Dependencies. Otherwise, the JAR won't be properly formatted to work with OSGi. 

To do that, include the following in your maven-bundle-plugin section:

<Embed-Dependency>!*log4j;scope=compile|runtime;type=!pom</Embed-Dependency>
<Embed-Transitive>true</Embed-Transitive>
<Import-Package>*;resolution:=optional</Import-Package>

After doing that, add <scope>provided</scope> to the section for each dependency that is included with Cytoscape (i.e. Cytoscape APIs and OSGi). 

Also, make sure to remove the maven-shade-plugin section from your pom.xml.

Let me know if this works...

Tim

michael...@non.agilent.com

unread,
Jul 14, 2014, 6:14:43 PM7/14/14
to cytoscape...@googlegroups.com

Tim, you deserve a prize!!

 

With just a few changes from what you sent me, I got things working!

 

For your edification, here are the changes I made to get it working:

1) Added ';inline=true' to the Embed-Dependency to directly add the classes versus adding a bunch of jars to the final uber jar file.

2) Removed '!*log4j;' in Embed-Dependency to stop the plugin including every single dependency (it seems to cause <scope>provided</scope> statements to be ignored).

2) Removed <Embed-Transitive>true</Embed-Transitive> to stop strange errors about missing MANIFEST files for dependency packages.

 

Once again, thanks for saving me Tim!!

Reply all
Reply to author
Forward
0 new messages