9

I am facing issues while using enum in my J2EE application. I am using enum in a switch case inside my stateless service bean.

During runtime I see following exception on switch statement:

Caused by: java.lang.NoClassDefFoundError: com/comp/service/TestServiceImpl$1

This issue has been extensively discussed on one of the thread on SO. But I do not see any solution mentioned to resolve this issue.

In my case I use JBOSS EAP6.1 server. JDK version is 1.7. Code is built using Maven in Eclipse IDE. And application is deployed as EAR archive. How do I add this extra generated class file in classpath inside my EAR archive? Is there any other way to resolve this issue?

Update 29 June 2014: I tried to build application from command line. Then this extra class file is generated. And I am able to deply and execute application successfully. It seems to be bug with eclipse then. Any idea how to resolve it?

pom.xml from EAR project:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <artifactId>demo-maven</artifactId>
        <groupId>com.comp.demo</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <artifactId>demo-ear</artifactId>
    <packaging>ear</packaging>

    <name>demo - ear</name>

    <url>www.comp.com</url>
    <licenses>
        <license>
            <name>Apache License, Version 2.0</name>
            <distribution>repo</distribution>
            <url>http://www.apache.org/licenses/LICENSE-2.0.html</url>
        </license>
    </licenses>

    <dependencies>

        <!-- Depend on the ejb module and war so that we can package them -->
        <dependency>
            <groupId>com.comp.demo</groupId>
            <artifactId>demo-web</artifactId>
            <type>war</type>
        </dependency>
        <dependency>
            <groupId>com.comp.demo</groupId>
            <artifactId>demo-service</artifactId>
            <type>ejb</type>
        </dependency>
    </dependencies>

    <build>
        <finalName>${project.parent.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-ear-plugin</artifactId>
                <version>${version.ear.plugin}</version>
                <configuration>
                    <!-- Tell Maven we are using Java EE 6 -->
                    <version>6</version>
                    <!-- 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>
                    <modules></modules>
                    <fileNameMapping>no-version</fileNameMapping>
                </configuration>
            </plugin>
            <!-- The JBoss AS plugin deploys your ear to a local JBoss EAP container -->
            <!-- Due to Maven's lack of intelligence with EARs we need to configure 
                the jboss-as maven plugin to skip deployment for all modules. We then enable 
                it specifically in the ear module. -->
            <plugin>
                <groupId>org.jboss.as.plugins</groupId>
                <artifactId>jboss-as-maven-plugin</artifactId>
                <configuration>
                    <skip>false</skip>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <profiles>
        <profile>
            <!-- When built in OpenShift the 'openshift' profile will be used when invoking mvn. -->
            <!-- Use this profile for any OpenShift specific customization your app will need. -->
            <!-- By default that is to put the resulting archive into the 'deployments' folder. -->
            <!-- http://maven.apache.org/guides/mini/guide-building-for-different-environments.html -->
            <id>openshift</id>
            <build>
                <plugins>
                    <plugin>
                        <artifactId>maven-ear-plugin</artifactId>
                        <version>${version.ear.plugin}</version>
                        <configuration>
                            <outputDirectory>deployments</outputDirectory>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>

</project>

pom.xml from ejb project:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <artifactId>demo-maven</artifactId>
        <groupId>com.comp.demo</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <artifactId>demo-service</artifactId>
    <packaging>ejb</packaging>

    <name>demo - service</name>

    <url>www.comp.com</url>
    <licenses>
        <license>
            <name>Apache License, Version 2.0</name>
            <distribution>repo</distribution>
            <url>http://www.apache.org/licenses/LICENSE-2.0.html</url>
        </license>
    </licenses>

    <dependencies>

        <!-- Declare the APIs we depend on and need for compilation. All of them 
            are provided by JBoss EAP 6 -->

        <!-- Import the EJB API, we use provided scope as the API is included in 
            JBoss EAP 6 -->
        <dependency>
            <groupId>org.jboss.spec.javax.ejb</groupId>
            <artifactId>jboss-ejb-api_3.1_spec</artifactId>
            <scope>provided</scope>
        </dependency>

        <!-- Import the CDI API, we use provided scope as the API is included in 
            JBoss EAP 6 -->
        <dependency>
            <groupId>javax.enterprise</groupId>
            <artifactId>cdi-api</artifactId>
            <scope>provided</scope>
        </dependency>

        <!-- Import the JPA API, we use provided scope as the API is included in 
            JBoss EAP 6 -->
        <dependency>
            <groupId>org.hibernate.javax.persistence</groupId>
            <artifactId>hibernate-jpa-2.0-api</artifactId>
            <scope>provided</scope>
        </dependency>

        <!-- JSR-303 (Bean Validation) Implementation -->
        <!-- Provides portable constraints such as @Email -->
        <!-- Hibernate Validator is shipped in JBoss EAP 6 -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <scope>provided</scope>
        </dependency>


        <dependency>
            <groupId>org.jboss.ejb3</groupId>
            <artifactId>jboss-ejb3-ext-api</artifactId>
            <version>2.0.0-redhat-2</version>
            <type>jar</type>
            <scope>provided</scope>
        </dependency>

        <!-- Test scope dependencies -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-all</artifactId>
            <version>1.9.5</version>
            <scope>test</scope>
        </dependency>
        <dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-entitymanager</artifactId>
    <version>4.3.5.Final</version>
    <scope>test</scope>
</dependency>


        <!-- Optional, but highly recommended -->
        <!-- Arquillian allows you to test enterprise code such as EJBs and Transactional(JTA) 
            JPA from JUnit/TestNG -->
        <dependency>
            <groupId>org.jboss.arquillian.junit</groupId>
            <artifactId>arquillian-junit-container</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.jboss.arquillian.protocol</groupId>
            <artifactId>arquillian-protocol-servlet</artifactId>
            <scope>test</scope>
        </dependency>

<dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>6.0</version>
            <type>jar</type>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <artifactId>maven-ejb-plugin</artifactId>
                <version>${version.ejb.plugin}</version>
                <configuration>
                    <!-- Tell Maven we are using EJB 3.1 -->
                    <ejbVersion>3.1</ejbVersion>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <profiles>
        <profile>
            <!-- The default profile skips all tests, though you can tune it to run 
                just unit tests based on a custom pattern -->
            <!-- Seperate profiles are provided for running all tests, including Arquillian 
                tests that execute in the specified container -->
            <id>default</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <build>
                <plugins>
                    <plugin>
                        <artifactId>maven-surefire-plugin</artifactId>
                        <version>${version.surefire.plugin}</version>
                        <configuration>
                            <skip>true</skip>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>

        <profile>
            <!-- An optional Arquillian testing profile that executes tests in your 
                JBoss EAP instance -->
            <!-- This profile will start a new JBoss EAP instance, and execute the 
                test, shutting it down when done -->
            <!-- Run with: mvn clean test -Parq-jbossas-managed -->
            <id>arq-jbossas-managed</id>
            <dependencies>
                <dependency>
                    <groupId>org.jboss.as</groupId>
                    <artifactId>jboss-as-arquillian-container-managed</artifactId>
                    <scope>test</scope>
                </dependency>
            </dependencies>
        </profile>

        <profile>
            <!-- An optional Arquillian testing profile that executes tests in a remote 
                JBoss EAP instance -->
            <!-- Run with: mvn clean test -Parq-jbossas-remote -->
            <id>arq-jbossas-remote</id>
            <dependencies>
                <dependency>
                    <groupId>org.jboss.as</groupId>
                    <artifactId>jboss-as-arquillian-container-remote</artifactId>
                    <scope>test</scope>
                </dependency>
            </dependencies>
        </profile>

    </profiles>

</project>
Community
  • 1
  • 1
user613114
  • 2,731
  • 11
  • 47
  • 73
  • Include *all* class files created by javac into the archive. - This seems to be a class (enum) declared within another class (TestServiceImpl) and so the compiler creates the (additional) class file. – laune Jun 29 '14 at 05:00
  • I am building my application in eclipse. And I do not see maven build generating this class :( What do you propose? – user613114 Jun 29 '14 at 06:03
  • I updated question, with further analysis. – user613114 Jun 29 '14 at 06:35
  • The only question here is whether that .class file appears under its correct name and package hierarchy in your .JAR, .WAR, or .EAR files. – user207421 Jun 29 '14 at 07:19
  • When i build application in maven, this class file does not appear. When I build application from command line and then refresh workspace in eclipse, that file is visible. – user613114 Jun 29 '14 at 07:36
  • Maybe if you post the pom driving maven, someone knowing maven could help (not me). - What I've done: If it is a simple matter of compiling java sources and then packing them into an archive, I've relied on Eclipse doing the compilation and its wizard to create a jar. There's also an ear wizard. - As an alternative: why not put that enum in a file of its own? – laune Jun 29 '14 at 07:37
  • Enum is in its own file only. I have used that enum in switch case in service Impl class. I have given reference to an SO link in my question. That question explains the exact issue I am facing. But I dont see any resolution. I will update my question with pom.xml details. – user613114 Jun 29 '14 at 07:43

3 Answers3

1

I ran into a similar issue, and the easy workaround was to define the Enum as public instead of private.

(Didn't have time to verify, but my hunch is that this causes the class to not be created as Name$1.class but rather something like Name$Enumname.class, which seemed to be the problem)

uncrase
  • 644
  • 1
  • 8
  • 16
1

In my case, to avoid that NoClassDefFoundError in the code line of the switch statement, the only solution i saw was to replace switch statement by "else if" statements:

        if (enumValue == EnumClass.Enum1) {
            ....
        } else if (enumValue == EnumClass.Enum2) {
            ....
        } else if (enumValue == EnumClass.Enum3) {
            ....
        } else {
            ....
        }

Exception caused by:

Caused by: java.lang.ClassNotFoundException: com.test.services.impl.MyServiceImpl$1
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1358)
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1180)

Test with Java 8, Tomcat 8.5, Spring boot.

Vikcen
  • 153
  • 2
  • 9
0

I have a project configuration quite similar to yours: eclipse, Maven, JDK 1.6, JBoss EAP6.2, and I have the same problem with a java.lang.NoClassDefFoundError when using an enum in a switch case.

I have found a workaround for it: generate an ear file (it is a war in my case) and install it manually from the JBoss administration console. I noticed the war includes the $1 needed classes and then you won't get the exception.

This is just a workaround, but it works for me. A good point of this workaround is that subsequent deployments done through eclipse work!

I will be listening to the answers to your question because I want a real solution.

Fer
  • 1,956
  • 2
  • 28
  • 35
  • Hello Fer,Thank you for your update. Even I do not have solution for this issue. Currently I am building my EAR from command line. And then refreshing workspace in eclipse nad deploying EAR in eclipse. It works for me. – user613114 Jul 02 '14 at 04:23
  • And what about subsequent deployments? Do you need to do this process always? In my case I need to do it only when I add or change something related to the enum. – Fer Jul 03 '14 at 06:33
  • I need to do command line build only if I clean the project in eclipse or make some changes in Enum. If I am making some other changes, I can then keep on building from eclipse. – user613114 Jul 07 '14 at 14:56
  • 1
    Can you try this? It is working for me! * Stop the JBoss * Refresh the target directory (right click on target directory and click Refresh) * Redeploy and start the JBoss – Fer Sep 04 '14 at 11:51