2

I'm new to Glassfish and Java EE although I've been using Java for a few years. I've inherited a project that stalled and now I need to start development on it again. I'm trying to deploy the web application as-is to see what works and what needs attention. While there is a lot of code to implement various functions, it appears that the first point needing attention is deployment of the application.

The web application I'm trying to deploy is MyServer and is packaged in a WAR archive. A class in MyServer has a reference to a class in MyDatabase which implements an interface (InterfaceOne) from MyInterfaces. The class in MyServer also has a direct reference to InterfaceOne from MyInterfaces. MyServer, MyDatabase and MyInterfaces are all projects in Eclipse and packaged using Maven. The MyServer POM file lists MyDatabase as a dependency and the POM file for MyDatabase lists MyInterfaces as a dependency. The MyServer POM file doesn't list MyInterfaces as an immediate dependency but I don't think that this should cause an issue. Eclipse doesn't show any errors in the MyServer class concerned; Eclipse appears to consider the Maven dependencies to be sufficient to locate all necessary classes.

When I deploy the MyServer WAR on Glassfish v3.1.2 via the Admin web console and then view the logs in ~glassfish3/glassfish/domains/MyDomain/logs/server.log I encounter the following errors:

[#|2014-05-29T10:06:02.371+0100|SEVERE|glassfish3.1.2|global|_ThreadID=80;_ThreadName=Thread-2;| Class [ my/interfaces/InterfaceOne] not found. Error while loading [ class my.server.ControllerOne ]|#] [#|2014-05-29T10:06:02.387+0100|SEVERE|glassfish3.1.2|global|_ThreadID=80;_ThreadName=Thread-2;|Class [ my/interfaces/InterfaceOne ] not found. Error while loading [ class my.server.ControllerOne ]|#]

There are two errors shown relating to the interface while trying to load the class from MyServer. If I remove either the reference to MyDatabase or the direct reference to InterfaceOne from MyInterfaces from the my.server.ControllerOne class then one of the errors above disappears (which is expected and just confirms that the error is related to the references (directly and indirectly) of the InterfaceOne from MyInterfaces.

Similar questions including here, here and here all mention ensuring that the required libraries (my-database.jar and my-interfaces.jar) are located in the WEB-INT/lib directory of the MyServer application's WAR archive. However, if I inspect the generated WAR archive for MyServer then the libraries are indeed located in the WEB-INF/lib/ directory. If I inspect the ~glassfish3/glassfish/domains/MyDomain/applications/MyServer/WEB-INF/lib/ directory after deployment the libraries are there too. I assume this indicates that they were successfully extracted from the WAR archive and placed on the Glassfish server. The point is the libraries are definitely there!

All I can think of is that the libraries are not added to classpath of the JVM trying to load the classes of MyServer but surely if Glassfish tries to load classes of an application then it should also first load the libraries packaged with the application shouldn't it? Indeed this page from the Oracle GlassFish Server Application Development Guide Release 3.1.2 indicates that the WEB-INF/lib/ directory of an application is added to the application's classpath.

I've seen other suggestions that libraries required by web applications be placed in the ~glassfish3/glassfish/domains/MyDomain/lib/ext/ directory. That might very well work but my specific libraries are required by the MyServer application only, not the whole of MyDomain. As far as I can tell, it should be valid to place them in the WEB-INF/lib/ directory of my application.

Does anyone have any ideas about why the my-database.jar and my-interfaces.jar libraries don't seem to be added to the classpath during deployment? More specifically, does anyone know why the my.interfaces.InterfaceOne class isn't visible while loading the my.server.ControllerOne class during deployment?

MyServer's web.xml content:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>MyServer</display-name>
  <welcome-file-list>
    <welcome-file>index.xhtml</welcome-file>
    <welcome-file>default.xhtml</welcome-file>
  </welcome-file-list>
  <servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>/faces/*</url-pattern>
  </servlet-mapping>
  <context-param>
    <description>State saving method: 'client' or 'server' (=default). See JSF Specification 2.5.2</description>
    <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
    <param-value>client</param-value>
  </context-param>
  <context-param>
    <param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
    <param-value>resources.application</param-value>
  </context-param>
  <context-param>
    <param-name>javax.faces.FACELETS_LIBRARIES</param-name>
    <param-value>/WEB-INF/balusc.taglib.xml</param-value>
  </context-param>
  <context-param>
    <param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
    <param-value>true</param-value>
  </context-param>
  <filter>
    <filter-name>PrimeFaces FileUpload Filter</filter-name>
    <filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>PrimeFaces FileUpload Filter</filter-name>
    <servlet-name>Faces Servlet</servlet-name>
  </filter-mapping>
  <context-param>
    <param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
    <param-value>false</param-value>
  </context-param>
</web-app>

MyServer pom.xml

<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>my.webapp</groupId>
    <artifactId>my-server</artifactId>
    <version>0.1.0-SNAPSHOT</version>
    <name>My Server</name>
    <parent>
        <groupId>my.webapp</groupId>
        <artifactId>my-parent-pom</artifactId>
        <version>1.5</version>
    </parent>
    <organization>
        <name>Example</name>
        <url>http://www.example.com</url>
    </organization>
    <repositories>
        <repository>
            <id>eclipselink</id>
            <url>http://www.eclipse.org/downloads/download.php?r=1&amp;nf=1&amp;file=/rt/eclipselink/maven.repo/</url>
        </repository>
    </repositories>
    <dependencies>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>6.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.faces</groupId>
            <artifactId>jsf-api</artifactId>
            <version>2.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.sun.faces</groupId>
            <artifactId>jsf-impl</artifactId>
            <version>2.1.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>eclipselink</groupId>
            <artifactId>eclipselink</artifactId>
            <version>2.3.0</version>
        </dependency>

        <dependency>
            <groupId>utilities</groupId>
            <artifactId>utilities</artifactId>
            <version>0.1.0</version>
        </dependency>

        <dependency>
            <groupId>javax.enterprise</groupId>
            <artifactId>cdi-api</artifactId>
            <version>1.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>my.webapp</groupId>
            <artifactId>my-database</artifactId>
            <version>0.1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.primefaces</groupId>
            <artifactId>primefaces</artifactId>
            <version>3.4.1</version>
        </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-io</artifactId>
        <version>1.3.2</version>
    </dependency>
    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.2.1</version>
    </dependency>
    </dependencies>

    <packaging>war</packaging>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <!-- <configuration> section added to pick up the WEB-INF/web.xml inside
                    WebContent -->
                <configuration>
                    <webResources>
                        <resource>
                            <directory>WebContent</directory>
                        </resource>
                    </webResources>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <scm>
        <connection>scm:svn:https://svn.server/location/in/repo/my_server</connection>
        <developerConnection>scm:svn:https://svn.server/location/in/repo/my_server/trunk</developerConnection>
    </scm>
</project>

MyDatabase pom.xml

<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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <artifactId>my-database</artifactId>
  <version>0.1.0-SNAPSHOT</version>
  <parent>
    <groupId>my.webapp</groupId>
    <artifactId>my-parent-pom</artifactId>
    <version>1.5</version>
  </parent>
  <dependencies>
    <dependency>
      <groupId>eclipselink</groupId>
      <artifactId>eclipselink</artifactId>
      <version>2.3.0</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.10</version>
        <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.mindrot</groupId>
      <artifactId>bcrypt</artifactId>
      <version>0.2.0</version>
    </dependency>
    <dependency>
        <groupId>my.webapp</groupId>
        <artifactId>my-interfaces</artifactId>
        <version>0.1.0-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>org.apache.geronimo.specs</groupId>
        <artifactId>geronimo-jpa_3.0_spec</artifactId>
        <version>1.1.1</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.0.5</version>
        <scope>test</scope>
    </dependency>
  </dependencies>
  <scm>
    <connection>scm:svn:https://svn.server/location/in/repo/my_database</connection>
    <developerConnection>scm:svn:https://svn.server/location/in/repo/my_database/trunk/</developerConnection>
  </scm>
  <groupId>my.webapp</groupId>
</project>

MyInterfaces pom.xml

<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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>my.webapp</groupId>
  <artifactId>my-interfaces</artifactId>
  <version>0.1.0-SNAPSHOT</version>
   <packaging>jar</packaging>
  <parent>
      <groupId>my.webapp</groupId>
      <artifactId>my-parent-pom</artifactId>
      <version>1.5</version>

  </parent>
  <scm>
    <connection>scm:svn:https://svn.server/location/in/repo/my_interfaces</connection>
    <developerConnection>scm:svn:https://svn.server/location/in/repo/my_interfaces/trunk</developerConnection>
  </scm>
  <dependencies>
    <dependency>
        <groupId>my.webapp</groupId>
        <artifactId>my-utilities</artifactId>
        <version>0.1.2</version>
        <classifier>me</classifier>
    </dependency>
      <dependency>
      <groupId>javax</groupId>
      <artifactId>javaee-api</artifactId>
      <version>6.0</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.10</version>
      <scope>test</scope>
    </dependency>
      </dependencies>
</project>

The MyInterfaces POM lists a dependency on MyUtilities. I think this can be safely ignored for this question since none of it's classes appear in the error messages I've described. It is also placed in the WEB-INT/lib/ directory on the Glassfish server when my application is deployed.

(Glassfish questions appear to require a lot of info like web.xml files and pom.xml etc. Thanks for taking the time to sift through all of this.)

Community
  • 1
  • 1
user3337410
  • 94
  • 1
  • 10
  • Please add your `pom.xml` to the question. – unwichtich May 29 '14 at 17:04
  • Is there something specific in the POMs you are looking for? Since the libraries are placed in the WEB-INF/lib directory on the Glassfish server during deployment I don't know what it is in the POMs that may help resolve this. Of course, that may be why I'm having this problem in the first place... – user3337410 May 30 '14 at 12:22
  • Nothing specific, it just makes it easier to understand the packaging. Is the `utilities` dependency in the my-server-pom.xml the same as the `my-utilities` dependency in my-interfaces-pom.xml? It may cause that the wrong version of `my-utilities` is packaged in the webapp. – unwichtich May 30 '14 at 13:45
  • No, they're not the same. They just have similar names to keep me on my toes. – user3337410 May 30 '14 at 13:57
  • Strange stuff, I have setup a basic project with the same structure and it works. I noticed that the error message one time mentions `my/interface` and one time `my/interfaces`. Is this correct or some kind of typo? – unwichtich May 30 '14 at 14:22
  • That was a typo, I've fixed it now. From what I've been able to find, the whole point of the WEB-INF/lib/ directory is to make application specific libraries available to the application. – user3337410 May 30 '14 at 14:28
  • Yes that's correct. Is the my-utilities.jar in `WEB-INF/lib`? – unwichtich May 30 '14 at 14:34
  • yip, all the libraries are there. The issue is that the classes they contain aren't visible when the MyServer classes are loaded during deployment. Glassfish has separate Deploy and Launch actions. I'd expect Deploy to upload, extract the WAR and register anything that needs to be registered. I'd expect the Launch action to actually load classes and start processes. Why are classes being loaded when I deploy? – user3337410 May 30 '14 at 14:36

2 Answers2

0

I have set up a project with basically the same structure as you described and I can't reproduce the problem nor do I have an additional idea what could be wrong.

Therefore I have pushed my test project to GitHub so you can try it and maybe you find any hint what is different in your project.

The project is here: https://github.com/erdbeerschnitzel/war-packaging

If you don't have a GitHub account to clone the project you can download the ZIP (button on the lower right). Extract it somewhere and load the 5 projects in your IDE, build everything and deploy the WAR file of the my-server project.

I left out the parent project and removed some dependencies like eclipselink and primefaces but I think that shouldn't make the difference.

Good luck.

Update:

Glassfish has separate Deploy and Launch actions. I'd expect Deploy to upload, extract the WAR and register anything that needs to be registered. I'd expect the Launch action to actually load classes and start processes. Why are classes being loaded when I deploy?

Actually the application (and therefore the classes) is loaded when you deploy it.

unwichtich
  • 13,712
  • 4
  • 53
  • 66
0

It appears that there were two issues at play:

  1. Firstly MyServer's web.xml <display-name> was incorrect. This wasn't visible in my question because I'd changed the library names (which contain client names). Part of the requirements given to me for the project were to rebrand the project and I missed the <display-name> element. Oops.

  2. The second issue was that, while investigating this issue, I moved the MyDatabase and MyInterfaces libraries from the MyServer WEB-INF/lib/ directory to the domain's lib/ext/ directory and back. This changed the errors logged during deployment (since the libraries were visible despite the incorrect <display-name> but they errors didn't reappear when I moved the database and interface libraries back into the MyServer application. I think Glassfish was caching the libraries and not updating the cached libraries during deployment. Stopping/starting the domain updated the cache.

To summarise, once the <display-name> of MyServer was changed and the Glassfish library cache was updated, the class loading errors appear resolved.

user3337410
  • 94
  • 1
  • 10