eclipse: external CDI in EJB module: NoClassDefFoundError - java

My current project consisting of a war and ejb module, is using a jar (incorperated via maven). This jar contains a CDI component which, when I inject this in the war module it works as expected, but when I inject this in my ejb module I get a NoClassDefFoundError during startup from my WAS 8.5 in eclipse (full profile).
When I start the server first, add the inject later and republish it seems to work. Also when I use Liberty profile it works. Also on Z/os and IPAS it works as expected.
I think it might has something todo with classloading, but have no idea how to solve this properly.
Using Eclipse Neon, WAS 8.5.5.11 full profile , jee6
Project is using java 8 while the component is using java 6
This is the first part of the stacktrace:
[13-9-17 14:54:26:589 CEST] 0000003e InjectionProc W CWNEN0047W: Resource annotations on the fields of the BestelFacade class will be ignored. The annotations could not be obtained because of the exc
eption : Logger
at java.lang.Class.getDeclaredFieldsImpl(Native Method)
Thanks

I found a way to get the job done, but I'm not sure if this is a proper solution or just a workaround while masking the real problem.
When I take a look at the ear module assembly I see in the source column c:/ws/.../jar and in the deploy path lib/jar
when I change the source into /..ear/target/../jar it works

Try setting the <bundleDir>/</bundleDir>
This will place the external jar/ejb not in lib, but in the root.
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<configuration>
...........
<defaultLibBundleDir>lib</defaultLibBundleDir>
<modules>
<jarModule>
<groupId>groupId</groupId>
<artifactId>artifactId</artifactId>
<bundleDir>/</bundleDir>
</jarModule>
</modules>
</configuration>
</plugin>

Related

Read POM values in external application properties

I have the following properties in the pom file
<name>DemoApplication</name>
<description>Demo spring project</description>
<version>1.0.0-SNAPSHOT</version>
And I have a class that reads the properties from application.yml
But instead of using the application.yml under src/main/resources I am specifying the properties through an external file as follows
java -jar DemoApplication-1.0.0-SNAPSHOT.jar --spring.config.location=application.yml
In this external application properties, I have the following attributes
swagger:
apiTitle: '#project.name#'
apiDescription: '#project.description#'
apiVersion: '#project.version#'
The issue is that the #project.name# and other properties are not being replaced as expected, but are read as-is.
How should the problem be approached?
According that section of the official documentation of Spring Boot v2, you can configure it with :
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<configuration>
<delimiters>
<delimiter>#</delimiter>
</delimiters>
<useDefaultDelimiters>false</useDefaultDelimiters>
</configuration>
</plugin>
With useDefaultDelimiters set to false or to true depending on your configuration.
The others sections of that official documentation will be helpful for your use case, especially these one : "77.5 Use YAML for External Properties".
If nothing is working, why don't you are loading a custom Properties file ? It could be loaded as you need without any problem. Just reference it with the correct path when you are starting your program, and inside your program, test if your file config.properties is available and contains what you need to work with.
Of course, the Maven way of loading resources files is the best easy way to go, and it should be a simple Properties file too. I have done exactly that way inside the software I am released to manage my configuration :
Writing a app.properties
Loading that file with Maven at runtime with resource configuration
Expanding properties with classical syntax ${my.prop}
Run the program with a Maven task.
Of course, when you distribute your app as a jar, it is a bit different.
Maybe you can try to write your properties files within a Maven goal.

Integrating Cloudinary with Adobe AEM

I am trying to integrate Adobe AEM 6.3 (running on Java 1.8) with Cloudinary SDK. I have done the following but, keep hitting an exception that I am not able to resolve. Has anyone integrated Cloudinary with AEM and run into similar issues?
Add the dependency in the pom.xml for compiling the code.
<dependency>
<groupId>com.cloudinary</groupId>
<artifactId>cloudinary-core</artifactId>
<version>1.24.0</version>
</dependency>
<dependency>
<groupId>com.cloudinary</groupId>
<artifactId>cloudinary-http44</artifactId>
<version>1.24.0</version>
</dependency>
Build an OSGI plugin to ensure AEM gets the right jar files. For this purpose, I followed the steps to create a third party RESTful service example. To build the bundle, I had to explicitly download the following jar files: cloudinary-1.0.14.jar, cloudinary-core-1.21.0.jar, cloudinary-http44-1.21.0.jar, commons-codec-1.10.jar, commons-collections-3.2.2.jar, commons-lang3-3.1.jar, commons-logging-1.2.jar, httpclient-4.4.jar, httpmime-4.4.jar, jsp-api-2.0.jar
Despite creating a bundle that has httpclient, I get the following exception when trying to upload an image to Cloudinary. Here's code and the exception.
Code snippet
import com.cloudinary.*;
..
Cloudinary cloudinary = new Cloudinary("<<credentials>>");
...
File toUpload = new File("/Users/akshayranganath/Downloads/background-2633962_1280.jpg");
try {
Map uploadResult = cloudinary.uploader().upload(toUpload, ObjectUtils.emptyMap());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Exception
Caused by: java.lang.NoClassDefFoundError: javax/net/ssl/HostnameVerifier
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:756)
at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.defineClass(BundleWiringImpl.java:2370)
at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.findClass(BundleWiringImpl.java:2154)
at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1542)
at org.apache.felix.framework.BundleWiringImpl.access$400(BundleWiringImpl.java:79)
at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:2018)
at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
at org.apache.http.impl.conn.SchemeRegistryFactory.createDefault(SchemeRegistryFactory.java:52)
at org.apache.http.impl.client.AbstractHttpClient.createClientConnectionManager(AbstractHttpClient.java:321)
at org.apache.http.impl.client.AbstractHttpClient.getConnectionManager(AbstractHttpClient.java:484)
at org.apache.http.impl.client.AbstractHttpClient.createHttpContext(AbstractHttpClient.java:301)
at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:818)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:55)
at com.cloudinary.Uploader.callApi(Uploader.java:317)
at com.cloudinary.Uploader.upload(Uploader.java:57)
at com.aem.community.core.models.HelloWorldModel.init(HelloWorldModel.java:59)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.sling.models.impl.ModelAdapterFactory.invokePostConstruct(ModelAdapterFactory.java:792)
at org.apache.sling.models.impl.ModelAdapterFactory.createObject(ModelAdapterFactory.java:607)
... 211 common frames omitted
Caused by: java.lang.ClassNotFoundException: javax.net.ssl.HostnameVerifier not found by MyBundle [550]
at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1574)
at org.apache.felix.framework.BundleWiringImpl.access$400(BundleWiringImpl.java:79)
at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:2018)
at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
... 236 common frames omitted
This is the first time I am working with AEM and I may not be following the right steps. Please let me know if anyone has been able to get past this issue.
Update
Based on Alexander's suggestion and a pointer from another source, I added the following code to the parent pom.xml file.
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>3.5.0</version>
<configuration>
<instructions>
<Embed-Dependency>*;scope=compile|runtime</Embed-Dependency>
<Embed-Directory>OSGI-INF/lib</Embed-Directory>
<Embed-Transitive>true</Embed-Transitive>
</instructions>
</configuration>
</plugin>
After making this change, the cloudinary libraries were being added to the bundle. Here's the output from AEM: http://localhost:4502/system/console/bundles
Embedded-Artifacts: OSGI-INF/lib/cloudinary-http44-1.21.0.jar; g="com.cloudinary"; a="cloudinary-http44"; v="1.21.0", OSGI-INF/lib/commons-lang3-3.1.jar; g="org.apache.commons"; a="commons-lang3"; v="3.1", OSGI-INF/lib/httpclient-4.4.jar; g="org.apache.httpcomponents"; a="httpclient"; v="4.4", OSGI-INF/lib/httpcore-4.4.jar; g="org.apache.httpcomponents"; a="httpcore"; v="4.4", OSGI-INF/lib/commons-logging-1.2.jar; g="commons-logging"; a="commons-logging"; v="1.2", OSGI-INF/lib/commons-codec-1.9.jar; g="commons-codec"; a="commons-codec"; v="1.9", OSGI-INF/lib/httpmime-4.4.jar; g="org.apache.httpcomponents"; a="httpmime"; v="4.4", OSGI-INF/lib/cloudinary-core-1.21.0.jar; g="com.cloudinary"; a="cloudinary-core"; v="1.21.0"
However, I now get an error with this message:
org.apache.avalon.framework.logger -- Cannot be resolved
org.apache.log -- Cannot be resolved
I am able to resolve the org.apache.avalon.framework.logger error by adding a dependency Avalon framework. But, I am not able to get over the org.apache.log issue. It looks like there is a version conflict that is causing the problem.
This new error starts when I include the Cloudinary http44 library. This library doesn't appear to directly reference logging (see here for dependencies). Due to this error, the application still fails to go from Installed to Active state.
Cloudinary-libs are available as Maven artifacts. Such JAR-files can be put in your bundle as private libraries with the maven-bundle-plugin.
The following sample works for me (even with Cloudinary test account)
...
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<executions>
<execution>
<!-- Create the bundle late in the compile-phase instead of the package-phase.
So the generated OSGi meta-data is available during JUnit tests. -->
<id>run-before-tests</id>
<phase>process-classes</phase>
<goals>
<goal>bundle</goal>
</goals>
</execution>
</executions>
<configuration>
<instructions>
<Bundle-Name>Test Bundle</Bundle-Name>
<Embed-Dependency>*;groupId=com.cloudinary;scope=compile|runtime</Embed-Dependency>
<Embed-Directory>OSGI-INF/lib</Embed-Directory> <!-- not needed, but nice -->
<Embed-Transitive>true</Embed-Transitive>
</instructions>
</configuration>
</plugin>
...
<dependencies>
<dependency>
<groupId>com.cloudinary</groupId>
<artifactId>cloudinary-core</artifactId>
<version>1.24.0</version>
</dependency>
<dependency>
<groupId>com.cloudinary</groupId>
<artifactId>cloudinary-http44</artifactId>
<version>1.24.0</version>
</dependency>
...
In general embedding an external library can be from simple, cumbersome to impossible. It depends on the dependencies of the imported artifacts.
Check the dependency tree manually! (e.g. https://mvnrepository.com/)
You have to fiddle with 3 instructions:
Embed-Dependency
This are the libraries, that are put in your bundle. Be careful with the asterisk operator, otherwise you may include way too many dependencies (in case of AEM easily half of the internet). But do not include too less! Extract the built bundle.jar, to see what is actually included (in case of cloudinary it was easy).
Import-Package
Often the libs have way too many dependencies, especially if libs come an other ecosystem (like Spring or JEE containers), or have a lot of semi-optional dependencies. With this setting you can tell OSGi, that a bundle can be activated, even if certain dependencies are not available.
This is a real world example :
<Import-Package>
!com.sun.msv.*,
!org.apache.log4j.jmx.*,
!sun.misc.*,
!org.jboss.logging.*,
!org.apache.zookeeper.*,
*
</Import-Package>
Export-Package
Normally the library should be bundle-private. But sometimes you have to import differently, or the lib does something automatically. So you should always check in the system console, what your bundle is exporting. In case it is not right, you have to manually fiddle with this setting:
Here is an example:
<Export-Package>
!*.internal,
!*.internal.*,
!*.impl,
!*.impl.*,
com.mycompany.myproject.mybundle.*
</Export-Package>
By default all packages * are exported, except they are named impl or internal. Also their child packages are private (the !*.impl.* rule). If the default doesn't work, then export with this instruction only what you need.
Whatever you export goes to the global OSGi space. As also the AEM- and Sling-Bundles are not perfect nor 100%-bugfree, please make sure
the startup/shutdown order of out-of-the-box AEM bundles should not be changed
a deployment, re-deployment or un-deployment of your code should not start/stop any out-of-the-box AEM bundles.
If you don't ensure this, you might experience strange deployment issues - that are very difficult to find/solve.
So the best is, NOT to export anything that is imported by any AEM out-of-the-box bundle. Everything else is for Experts-only. And even they overestimate themselves, and underestimate the long-term costs of patching AEM manually.
PS: the _removeheaders instruction could remove all osgi-instructions that are not needed for runtime. But only do this, if you want to provide a bundle to the public and make it totally shiny. I would leave it in, as it is some kind of documentation.

How to use httpcomponents in wildfly 10 with EAR project?

I can't get org.apache.httpcomponents to work in Wildfly 10. I didn't try 9. The error I get is, basically.
Caused by: java.lang.ClassNotFoundException: org.apache.http.client.methods.HttpUriRequest from [Module "deployment.opca-ear.ear.opca-ejb.jar:main" from Service Module Loader]
at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:198)
at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:363)
at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:351)
at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:93)
... 185 more
I looked at Wildfly 8.1 ClassNotFound org.apache.http.conn.ClientConnectionManager, but jboss-deployment-structure.xml described there is not working here.
I tried various combinations of things in the POM file, but I'm not getting anywhere with that.
The class fails when being constructed, so the import statements are causing problems.
I haven't been able to get access to the module or get the needed jar files to be deployed into the ear lib directory.
EDIT: I'm using JBoss Developer Studio. I seem to be making some progress in that if I copy my opca-ear.ear file to the deployment directory manually then the httpclient and httpcore jars get deployed, but they don't if I deploy from jbstudio, so I guess it's an issue with jboss-modules.jar deployments. Not being able to debug/deploy from jbstudio is going to be a pain. Httpclient and httpcore are in my opca-ear.ear file in the lib directory, as well as the ejb/target/opca-ear/lib directory.
If I could get something like jboss-deployment-structure.xml or perhaps an entry in the a manifest file working so that wildfly provides the client access to the org.apache.httpcomponents resources then I wouldn't have to worry about jboss-modules.jar.
SOLUTION: As noted in the accepted answer, jboss-deployment-structure.xml only works on "full" deployments, so I used a manifest.mf entry
Dependencies: org.apache.httpcomponents
and updated the maven-ejb-plugin to use it:
<artifactId>maven-ejb-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<!-- Tell Maven we are using EJB 3.1 -->
<ejbVersion>3.1</ejbVersion>
<archive>
<manifestFile>${basedir}/src/main/resources/META-INF/manifest.mf</manifestFile>
</archive>
</configuration>
It all depends on which code needs it. The jboss-deployment-structure.xml you are mentionning isn't going to work if you don't declare your 'full' application.
Maybe you should just add a Manifest with the entry Dependencies: org.apache.httpcomponents in the jar/war that needs it.
Tkae a look at https://docs.jboss.org/author/display/WFLY10/Class+Loading+in+WildFly

Jenkins Error starting static Resources

Read almost all links under the title (when creating topic) and more of them in google, did not find the answer.
So, the problem is: jenkins builds maven web project. I installed the Deploy plugin, so that jenkins would publish .WAR file to tomcat.
Tests section passed and WAR file is built - OK, but when jenkins starts to
[INFO] --- tomcat7-maven-plugin:2.1:run (default-cli) # webapp ---
I see:
ERROR] Error starting static Resources
java.lang.IllegalArgumentException: Document base /var/lib/jenkins/workspace/AppFolder/AppName/src/main/webapp does not exist or is not a readable directory
And if I look to the project's folder, there really is no such folder, because it is:
/var/lib/jenkins/workspace/AppFolder/AppName/src/com/companyname/webapp
so, I just don't know where to fix the path. Tried to edit pom.xml:
<build>
<sourceDirectory>src/com/companyname</sourceDirectory>
...
</build>
Just don't get it. Where that path is specified?
Looks like I made errors in configuration.
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration> ... <configuration>
Now everything works. Thanks for your concern.
I think this email might help you. Have a read through it, but from what I can see this is the important part (Tomcat Maven docs - warSourceDirectory).
Quote:
<configuration>
<warSourceDirectory>target/${artifactId}-${version}</warSourceDirectory>
will be better with
<warSourceDirectory>${project.build.outputDirectory}/${artifactId}-${version}</warSourceDirectory>
</configuration>

Avoid version number from context root of web application

I've web application. I'm using maven to build this application. I get a war file when i build application: my-service-1.0.0-SNAPSHOT.war. While accessing the services over http, i have to make a call like this:
http://localhost:8080/my-service-1.0.0-SNAPSHOT/......
I don't want version number in my context name. I'm using tomcat as container. Do i have to set context root for this under Web-Inf as we do it in case of jboss ? Does it depend based on the type of container we use ?
Using maven you can set a variable in your pom.xml file to store your final build name and in your war plugin configuration you pass it. Something like this:
<build>
<finalName>my-service</finalName>
</build>
Then in your plugin configuration:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.0</version>
<configuration>
<webappDirectory>/path_to_deploy_folder/${project.build.finalName}.war</webappDirectory>
</configuration>
</plugin>
You did not mention whether you are using maven to deploy into tomcat container. If you're creating a production environment you probably won't be using maven at least for local deployments. In that case I don't think it's a bad idea to rename your war file. For example if you want you webapp root to be at https://mydomain.com/subdomain/myteam/myapp then simply rename my-service-1.0.0-SNAPSHOT.war to subdomain#myteam#myapp.war with '/' being replaced by '#'

Categories

Resources