Eclipse + Maven + JavaServer Faces -> ClassNotFoundException: StartupServletContextListener - java

Summary
When I try to run a JSF 2.0 application from within Eclipse (on Tomcat 7.0) I get the following exception:
Problem: SEVERE: Error configuring application listener of class org.apache.myfaces.webapp.StartupServletContextListener
java.lang.ClassNotFoundException: org.apache.myfaces.webapp.StartupServletContextListener
Details
I'm learning to develop JSF applications, using Eclipse.
I started with a preconfigured Eclipse project: File->New->Dynamic Web Project->JavaServer Face v2.0 Project.
Using this method Eclipse provides all dependencies. But I want to really learn how everything works. I want to remove the "magic", so I converted my project to a Maven project: Configure->Convert to Maven project.
I then created my pom.xml (based on http://myfaces.apache.org/build-tools/archetypes/myfaces-archetype-helloworld20/index.html), it contains the following:
<build>
<finalName>jsf-facelets-tutorial</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webXml>WebContent/WEB-INF/web.xml</webXml>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>javax.el</groupId>
<artifactId>el-api</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.myfaces.core</groupId>
<artifactId>myfaces-api</artifactId>
<version>2.0.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.myfaces.core</groupId>
<artifactId>myfaces-impl</artifactId>
<version>2.0.5</version>
<scope>runtime</scope>
</dependency>
</dependencies>
But because I'm unfamiliar with JSF, and because this is an Eclipse "Dynamic Web Project", the project structure is new to me and I'm having trouble understanding which dependencies are coming from Maven and which are provided by the Eclipse "magic".
In Eclipse, my project structure is as follows:
ProjectName
JAX-WS Web Services <-- CAN I REMOVE THIS???
Deployment Descriptor
Java Resources
src/main
Libraries
Apache Tomcat v7.0
el-api.jar
jsp-api.jar
[more...]
JSF 2.0 (Apache MyFaces JSF Core-2.0 API 2.0.2) <-- I REMOVED THIS!!!
EAR Libraries
JRE System Library
Maven Dependencies
el-api-1.0.jar
myfaces-api-2.0.5.jar
myfaces-impl-2.0.5.jar
[more...]
Web App Libraries
Problem
My (very basic) application (login page & welcome page) no longer runs.
When I do the following:
(1) Right click on WebContent/login.xhtml
(2) Run as -> Run on Server
(3) Apache Tomcat v7.0 - JDK6 at localhost
I get the exception:
Problem: SEVERE: Error configuring application listener of class org.apache.myfaces.webapp.StartupServletContextListener
java.lang.ClassNotFoundException: org.apache.myfaces.webapp.StartupServletContextListener
I have the feeling that this is very easy to fix, but I'm too unfamiliar with these frameworks to work it out.
If there are any additional details I should provide (web.xml, faces-config-xml, login.xhtml), let me know and I'll add them.
Thanks!
EDIT
WEB-INF/lib is always empty. From my understanding, it's necessary to copy all dependencies into this folder, that will be required at runtime, and that are not provided by the Web Container. The reasons mine is empty are: (1) I don't know what I need in there (2) I don't know how to automate the process of putting .jar files in there

Under your eclipse Project Properties, select Deployment Assembly from the navigation menu which defines "packaging structure for this Java EE Web Application project." Make sure you have all the project dependencies added here..
Or look into web server directory under workspace/.metadata/.plugins/org.eclipse.wst.server.core\tmp0 to check if the jars have been copied to catalina base.

Sounds like you don't have all the jars in your target folder ready to deploy to tomcat
Try running a maven package in eclipse, right click on project, run as maven package

Related

Can't resolve the error: java.lang.NoClassDefFoundError: org/json/simple/parser/ParseException

Trying to use Maven to organize my project and I keep running into the following error. I know that this error means the file is present at compile time but for some reason it can't be found at runtime.
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.NoClassDefFoundError: org/json/simple/parser/ParseException
So I'm working on a project in Java that will take a user query, search Google Images and then download some of the results onto my computer. To that end I've had to use some third party libraries like JSoup, Json-Simple, and Gson.
I initially added Jsoup to my classpath manually and it worked, but then I heard about Maven and started using it instead. My issue is that when I try to run my code I get the error above.
I'm just not sure how to resolve this. I've seen a bunch of other posts about similar errors and I've tried to modify my pom.xml accordingly but
I just can't get it to work. I've tried removing the ~/.m2 file, ran mvn clean, mvn install, mvn package, mvn compile, and it all works fine. But when it comes time to run, I keep getting that error.
Here's most of my pom.xml file.
<repositories>
<repository>
<id>central</id>
<name>Maven repository</name>
<url>http://repo1.maven.org/maven2</url>
</repository>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<!-- jsoup HTML parser library # https://jsoup.org/ -->
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.11.3</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.googlecode.json-simple/json-simple -->
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
FOUND SOLUTION: So I left out some parts of the pom.xml file to make it easier to read, and because all the other parts were generated by Maven itself so I figured there couldn't be an issue with anything there. But it adds a tag called "pluginManagement" that encloses all other plugins and apparently this does not allow the Shade plugin to run.
Between ngueno's guidance and this post Maven shade plugin is not called automatically for goal "package"
I was able to figure out my issue, though I'm still not entirely sure why it is an issue. Anyways, I figured I'd update this post in case someone else with a similar problem stumbles across it. This was on Mac OS btw, in case it makes a difference. Thanks for your help everyone.
Usually NoClassDefFound errors are related to missing libraries at runtime.
Since you are running using the terminal I supose you are building your project using Maven, and running the generated JAR,
I would recommend to you to use the maven-shade-plugin and generate an uber-jar as I explained on this question.
The purpose generating a uber-jar is to carry all the needed dependencies inside of it (available on the application classpath).
Implement the plugin and try to run using the new JAR.
PS: Remember to check this section related to Executable Jars
UPDATE: Remove the <scope>provided</scope> of your jsoup dependency, to enforce Maven to package it along your app, with the provided scope you are saying that this dependency will be provided by the JDK at runtime.
The jars that you identify in your dependencies must be present in the Runtime classpath.
This is not the classpath that is available when you compile the code;
it is the classpath on the host where you run the application.
You must install these jars on the target host.
Edit: More details
You must do the following:
Identify the runtime host.
Create a directory on the runtime host into which you will install the dependent jar files.
Include every jar in the classpath.
Consider abandoning the "roll-your-own" path.
If you use Spring Boot
(I like it,
I don't work for them).
One feature of spring boot is a reinvented "Fat Jar" that will include the dependencies inside one deliverable artifact (the fat jar) and will add them to the classpath at startup.
Edit:
The Spring boot executable jar file is not a "Fat Jar",
instead it includes the dependencies in a directory in the
executable jar and adds said jars to the classpath on startup.

Hibernate MultiMap cannot be found while code generation

While i'm trying generate some classes by Hibernate using existing db relation it generates some error:
org.hibernate.console.HibernateConsoleRuntimeException: Received a NoClassDefFoundError, probably the console configuration classpath is incomplete or contains conflicting versions of the same class
Received a NoClassDefFoundError, probably the console configuration classpath is incomplete or contains conflicting versions of the same class
org.hibernate.console.HibernateConsoleRuntimeException: Received a NoClassDefFoundError, probably the console configuration classpath is incomplete or contains conflicting versions of the same class
Received a NoClassDefFoundError, probably the console configuration classpath is incomplete or contains conflicting versions of the same class
java.lang.NoClassDefFoundError: org/apache/commons/collections/MultiMap
org/apache/commons/collections/MultiMap
java.lang.ClassNotFoundException: org.apache.commons.collections.MultiMap cannot be found by org.jboss.tools.hibernate.runtime.v_5_1_5.0.1.Final-v20160331-1852-B88
org.apache.commons.collections.MultiMap cannot be found byorg.jboss.tools.hibernate.runtime.v_5_1_5.0.1.Final-v20160331-1852-B88
My maven file:
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.firebirdsql.jdbc</groupId>
<artifactId>jaybird-jdk18</artifactId>
<version>2.2.10</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.1.0.Final</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.2</version>
</dependency>
I see apache common-collections jar in Maven Dependencies and i am able to use apache's MultiMap in my code.
I had the same issue. Here is how I fixed it:
Open Edit Configuration dialog and go to Classpath tab, remove project-name (default classpath), click the button "Add Projects..." to add your project.
Then it works.
Or you can try using previous version instead of v5.1. In hibernate perspective, "your configuration" / Edit configuration, Change hibernate version to previous version like v4.3.
Just to chime in: Eclipse Mars. Hibernate 5.1.0. JDK 8. As Gordon and Kevin mentioned above, changing the version of Hibernate to 4.3 in in Edit Configuration worked for me.
I changed the hibernate version of 5.1 to 4.3 in Console Configuration file.
Set hibernate perspective
Open Hibernate configuration tab
Click right on your configuration
Select Edit configuration
Change Hibernate Version of 5.1 to 4.3
Fix for me: Mars worked with Hibernate Tools plugin v. 5.1.4. I just needed to click "update" after "search for updates"

Running Tomcat Maven plugin with added project provided dependency

Need to be pointed in the right direction on this perhaps, but if I add a "provided" dependency that is not included in the tomcat set of provided dependencies, running tomcat7:run from within eclipse fails with a classnotfoundexception on the class from the provided scope jar.
It needs to "provided" because it's a custom jar from a separate project that I've run mvn install on and for production am copying the jar to the $CATALINA_BASE/shared directory so that it's available (as a singleton) across applications/webapps.
<dependency>
<groupId>IndexFileAccessTracker</groupId>
<artifactId>IndexFileAccessTracker</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
Only way I see (with my limited knowledge of Maven and the Tomcat7 plugin) is to change the scope to compile when running tomcat from the plugin in Eclipse and then change the scope back to provided when running the package goal.
Are there solutions to this? I tried adding the dependency to the the tomcat maven plugin (keeping the main maven dependency as provided but got the same class not found error:
<!-- For Maven Tomcat Plugin -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<path>/CounterWebApp</path>
</configuration>
<dependencies>
<dependency>
<groupId>IndexFileAccessTracker</groupId>
<artifactId>IndexFileAccessTracker</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
</plugin>
Again, it needs to be provided in the main Maven dependency because I don't want it included in the deployed WAR.
Resolved by using profiles, similar to https://stackoverflow.com/a/5951630
...
</dependencies>
<profiles>
<profile>
<id>runineclipse</id>
<dependencies>
<dependency>
<groupId>IndexFileAccessTracker</groupId>
<artifactId>IndexFileAccessTracker</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
</profile>
</profiles>
<build>
...
Then in my run/debug configuration just added runineclipse to the Profiles: box.
(On a side note, to do step through debugging I had to manually add the project to the Source tab.)
The build configuration was just the same package in the Goals: box; and I left the original dependency to have scope provided.
The tomcat7-maven-plugin and its run goal
Requires dependency resolution of artifacts in scope: test
Everythig that is on the compile classpath is also on the test classpath.
Thats why it is working with scope compile.
So the solution in your case would be to mark your dependency as test what even is (imo) semantically correct.
This will make the library available at local test-time, but not in the final artifact.

Maven EAR Project - JAR not being excluded?

I am trying to exclude a single library .JAR file from my EAR that is being built via Maven, as this library is included as a JBoss EAP module. I've followed the instructions in the documentation, but I always see this library included anyway. Here's what the relevant pom.xml section looks like:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<version>2.9</version>
<configuration>
<!-- Tell Maven we are using Java EE 6 -->
<version>6</version>
<finalName>MenuProject</finalName>
<!-- Use Java EE ear libraries as needed. Java EE ear libraries are
in easy way to package any libraries needed in the ear, and automatically
have any modules (EJB-JARs and WARs) use them -->
<defaultLibBundleDir>lib</defaultLibBundleDir>
<packagingExcludes>**/postgresql*.jar</packagingExcludes>
<modules>
<!-- Register our War as a web module, and set the context root -->
<webModule>
...
As you see, I'm trying to exclude the postgresql*.jar file from being included in my EAR file. But, when I do a build I still see it.
Am I misunderstanding this functionality? Or am I doing it wrong? Any advice?
UPDATE: I should add, this library is added as a dependency for another library that my app depends on. That is why it is being introduced in the first place. I do not need it included in the EAR, as it is available as a JBoss EAP module.
Wrap your dependency type in a project object model pom as a type:
<dependency>
<groupId>${project.that.has.postgres.as.dependency.groupId}</groupId>
<artifactId>${project.that.has.postgres.as.dependency.artifactId}</artifactId>
<version>${project.that.has.postgres.as.dependency.version}</version>
<type>pom</type>
</dependency>

Best Approach to Set Up External Dependency in Maven

I hope I'm explaining this as accurately as possible, and I want to know if I set up the maven dependencies correctly, or if there's a better way to do it.
Most of my development team's projects rely on a home-grown jar that is deployed at server class loader. The reason for this jar to reside at this level is to the ease of updating the jar at one place without repackaging each project that's using it, assuming changes made to it are backward-compatible.
I develop my web apps against Jetty in my local development. So, in order for the web apps to work locally, I set up the dependencies this way:-
<dependencies>
<!-- Configuring external jar dependency -->
<dependency>
<groupId>com.test.app</groupId>
<artifactId>app-jar</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${env.EXTERNAL_JAR}</systemPath>
</dependency>
...
</dependencies>
<build>
<plugins>
<!-- Configuring Jetty -->
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.26</version>
<configuration>
<contextPath>/${project.parent.artifactId}</contextPath>
<jettyEnvXml>${env.JETTY_ENV_XML}</jettyEnvXml>
<scanIntervalSeconds>1</scanIntervalSeconds>
<connectors>
<connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
<port>7777</port>
</connector>
</connectors>
<webAppConfig>
<extraClasspath>${env.EXTERNAL_JAR}</extraClasspath>
</webAppConfig>
</configuration>
</plugin>
...
</plugins>
</build>
In this approach, I set up an environment variable that points to the external jar path, and reference it in my pom.xml as ${env.EXTERNAL_JAR}.
After doing some reading, it seems like using "system" scope is considered a bad practice. So, I installed this external jar in Nexus and change the scope to "provided":-
<dependency>
<groupId>com.test.app</groupId>
<artifactId>app-jar</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
This allows me to compile my project properly, but I'm not sure if it is even possible for me to get rid of the "EXTERNAL_JAR" environment variable completely because it's still needed by Jetty for the runtime to work properly. My take is using "provided" scope is a little tedious and more work, because I now need to remember to update the jar in Nexus when it is modified AND I still need to update the jar located at the path pointed by the environment variable.
Is there a way for me to expose the external jar to Jetty through maven dependencies, yet not being packaged into the project when the war file is built?
What are you advice on this? Should I just stick with "system" scope so that I just need to update the jar at one place, or should I use "provided" scope? Or if there's even a better way to do this?
Thanks much.
You should be able to add dependencies to the jetty plugin. And then I have the provided scope for the project itself.
http://docs.codehaus.org/display/JETTY/Maven+Jetty+Plugin
as in
<project>
...
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<configuration>
<systemProperties>
<systemProperty>
<name>logback.configurationFile</name>
<value>./src/etc/logback.xml</value>
</systemProperty>
</systemProperties>
</configuration>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>0.9.15</version>
</dependency>
</dependencies>
</plugin>
...
<project>
The best thing to do is setup an external repository with your dependency, and add it to your pom.
<repositories>
<repository>
<id>my-repo</id>
<name>my-repo</name>
<url>http://your.repo.url</url>
</repository>
</repositories>
and then you can add your dependency as
<dependency>
<groupId>com.test.app</groupId>
<artifactId>app-jar</artifactId>
<version>1.0</version>
</dependency>
I approve of provided. Provided means - download the dependency for compile-time, but I expect to see it on classpath on the application server.
I did not realize you care only for your local development, so the following would be useful if you were running Jetty on an external server:
Maven will let you deploy a file to a server using the Wagon plugin. So a part of your build process could be pushing the proper .jar into your Jetty server. That way you would not have to do it manually. I would prefer this solution to running a local Maven repository on the Jetty server as suggested by #Paul.
If you wanted to be super-clever (usually a bad idea), you might try to set up a repository directly on the machine with Jetty, that would serve the jar directly from your Jetty install. That way you would not have to modify Nexus, the jars would be only at one place. You can even set up Nexus to mirror another repository, so it could pick things up automatically.
It is a bad practice to modify .jar contents and keep the same Maven coordinates. So this "clever" approach would not work that great anyway.

Categories