Eclipse-wtp ear with 3rd party libs

issue-resolved
buildship

(Roman Wieser) #1

Currently i am trying to deploy a project on an ApplicationServer in Eclipse. Unfortunately all 3rd party libraries are missing. The deployment will end in a ClassNotFoundException (Or the first call).

My Environment:
Eclipse Neon.1a Release (4.6.1) 20161007-1200 for WebDevelopers
Gradle 3.1
Buildship 2.0+
WildFly 10.1.0.Final (and some JBossTools to import the AppServer)

I made a small project to reproduce:

The project consist of 2 parts. An ear part and an ejb part.

test_ear_deployment
|___ear
|___ejb (one bean and a dependency to apache.commons to fail with CNFE)
|___client (do the remote call)

As Server i defined the WildFly 10.1.0 and the ear project as deployment.

The ear part is pretty simple:

dependencies {
        deploy project(':ejb')
	earlib 'org.apache.commons:commons-lang3:3.5'
}

and the facets. applying ear, java, eclipse-wtp

The ejb part:

dependencies {
	compileOnly 'javax:javaee-api:7.0'
	compile 'org.apache.commons:commons-lang3:3.5'
}

applying java, eclipse-wtp

The Deployment Assembly of the ejb project does not have the lib in the deploy path.
Neither the ear project does, even if explicitly defined as earlib.

Calling “gradle build” builds the ear containing the third party lib ind the lib directory.
In Eclipse the 3rd party library is alway missing.

Looking at the org.eclipse.wst.common.compoents File, the apache.commons entry is missing. So any deployment on the AppServer withing Eclipse will end up in a ClassNotFoundException. Adding the missing entry by hand will fix the issue:

<dependent-module archiveName="commons-lang3-3.5.jar" deploy-path="/lib" handle="module:/classpath/lib/....lot..../commons-lang3-3.5.jar">
   <dependency-type>uses</dependency-type>
</dependent-module>

I saw there where changes in Gradle 3.0 (2.9 is working):
https://docs.gradle.org/3.0/release-notes#eclipse-wtp-handling-of-external-dependencies-changed

The issue is not with BuildShip but with gradle and how the components file is created.
Any project dependency works, any jar dependency does not work.
So i am wondering how to fix this issue? Am i doing something completly wrong?

Thanks in advance for any suggestions.


(Stefan Oehme) #2

That’s expected, since it’s not a war or ear, but just a utility project. The library is marked as

<attribute name="org.eclipse.jst.component.nondependency" value=""/>

on the classpath as expected.

It is defined on the classpath with

<attribute name="org.eclipse.jst.component.dependency" value="/lib"/>

Sounds like an issue in WTP, because it is supposed to pick these entries up from the classpath.


(Roman Wieser) #3

In order to do some manual testing, an new UserLibrary was created in Eclipse called ‘someuserlib’ and the jboss-client.jar is added to it to be distinct to the other container.
(Window - Preferences - (Java > Build Path > User Libraries).

EAR
The UserLib is added manually to the ear project and exported it. The ‘.classpath’ file is modified to “Publish/Export depdency” and looks like this:

<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer">
	<attributes>
		<attribute name="org.eclipse.jst.component.dependency" value="/lib"/>
	</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/someuserlib">
	<attributes>
		<attribute name="org.eclipse.jst.component.dependency" value="/lib"/>
	</attributes>
</classpathentry>
```

Neither the GradleClassPathContainer nore the UserLibrary is exported to the deployment.

The Eclipse Wiki states:
http://wiki.eclipse.org/Web_Tools_Platform_Release_3.0_Requirements/JavaCPvsJavaEEModDeps

> For EAR projects, assembly information must still be stored in the component file and specified fully using a Java EE Module Dependencies UI

According to this documentation it does not work on ear projects.
I do not have deep knowlegde in EclipsesWTP and the documentation may be outdated.



**EJB**

The ebj project is modified like the ear project. Finally, the '.classpath' file looks like the one from the EAR project. Both UserLib and GradleCPContainer are maked to export.
Both entries are now shown in the Deployment Assembly UI of the ejb project to be exported to '../lib'. The same UI of the ear project also shows the dependency of these 2 containers. This is like expected.

- Unfortunately, the dependency configured by the GradleCPC is not deployed to the application server (commons-lang3).
- The lib from the UserLib (jboss-client.jar) is deployed to the app server.

In this project setup the dependency attribute should work, as the UserLibs are copied to the deployment of the Application Server. Probably it is not intended to fiddle around in the '.classpath' files 'gradleclasspathcontainer' entry. This may cause the problem.

I made a screenshot to show this behaviour.

<img src="/uploads/default/original/2X/2/2af5f96a9d538c19b24da0f306797cff9d0a9c98.jpg" width="690" height="366">





- Is there any possibility to mark the ejb (not war, not ear) project to publish its classpath?
Convert ``org.eclipse.jst.component.nondependency`` into  ``org.eclipse.jst.component.dependency value="../lib"``
and let the Eclipse handle this.


- Is there any possibility to get the EARs libs to work? The only way is to write all depdendencies to the component file by hand i guess.

If anybody has ideas about this i would appreciate. Thanks in advance.

(Stefan Oehme) #4

If this is true, then the information we based our implementation on was wrong and they actually never implemented the classpath scanning for EAR projects. @donat can you investigate further into this?

If classpath entries don’t work for EAR projects, we need to go back to putting external libs into the component assembly descriptor, making it non-portable and making our logic inconsistent between WAR and EAR projects. I’d really like to avoid that unless it’s the only way.


(Donát Csikós) #5

I’ve spent some time on how the classpath attributes work on EAR projects, and it’s buggy to say the least. Fortunately the component descriptors are used for non-java EAR projects. @DerMuedeJoe You can make your sample project work if you remove the java plugin from the ear module.


(Stefan Oehme) #6

We’ll add a warning to Buildship in the future which tells users that applying both the java and ear plugins to the same project is not supported by WTP.


(Roman Wieser) #7

Thanks for doing a deeper look at the problem.
I have tried the supposed solution without applying the java plugin to the ear module. Unfortunately it does not change anything in the deployment. The deployment from wtp still lacks the thirds party library. (Am i doing something wrong?)

  • clone the project again (removed the java plugin)
  • Imported the project into Eclipse with the Buildship dialog
  • Created a new Server (WFly…)
  • Removed all deployments with “rm -rf” from the deployment directory to be sure there is no old incarnation left from other tests
  • Added the ear module to the server (with the “Add and Remove…” dialog on the server tab)
  • Published the ear module
  • Start the server and run the client
  • As expceted, the CNFE arises due to the missing lib

Neither the Deployment Descriptor/Bundled Libraries nor the bash shows the commons-lib:

To get this working, i did some handish xml modifications (working for this small test case):

def addDependentModuleNode(Node parentNode, String deployPath, File file) {
   groovy.util.Node dependentModule = new Node(parentNode, 'dependent-module')
   dependentModule.attributes().put ('deploy-path', deployPath)
   dependentModule.attributes().put ('handle', 'module:/classpath/lib/' + file.getAbsolutePath())
   groovy.util.Node dependencyType = new Node(dependentModule, 'dependency-type', 'uses')
}


eclipse.wtp.component.file {
  withXml {
     def wbModules = it.asNode().findAll { node -> node.name() == 'wb-module' }
     if (wbModules.size() != 1) {
        throw new StopActionException("wtp eclipse wb-module problem")
     }

     def node = wbModules.get(0)
     configurations.earlib.resolve().each {
        addDependentModuleNode(node, '/lib', it)
     }
  }
}

The deployment on the WildFly Server now adds the third party library into the deployment and a client call will not end in a ClassNotFoundException.
Its not the preferred way to get WTP to work but at least, the deployment seem to work.

Now the Deployment Descriptor / Bundles Libraries and the bash contains the library:


(Donát Csikós) #8

Judging from your screenshots, your ear project still applies the java plugin. In your sample project you declare it in the allprojects block in the root build script. Delete that, and apply the plugin on the appropriate sub-projects.


EAR project 3rd party dependencies
(Roman Wieser) #9

Yes. You are right. Missed this one. I am sorry.

When applying only the ear plugin but not the java plugin the depdendencies defined on earlib works.

Thank you for your support.


(Donát Csikós) #10

No problem at all. You helped us a lot with your detailed reports. We’ll probably do something about the java+ear combination.