1

I have a very simple ejb 3.0 module with maven, it has only two session beans one stateless and the other is singleton...when I am trying to deploy the project on Glassfish 3.0 server, I got this exception:

Error occurred during deployment: Exception while deploying the app : Invalid ejb jar : it contains zero ejb. Note: 1. A valid ejb jar requires at least one session, entity (1.x/2.x style), or message-driven bean. 2. EJB3+ entity beans (@Entity) are POJOs and please package them as library jar. 3. If the jar file contains valid EJBs which are annotated with EJB component level annotations (@Stateless, @Stateful, @MessageDriven, @Singleton), please check server.log to see whether the annotations were processed properly.. Please see server.log for more details.

I verify the project with the Glassfish Verifier Tool, I got this exception, but I don't know what should I do?

Verifier output unparsable
Verifier output (C:\Users\Mariam.Moustafa\Documents\NetBeansProjects\web\EmployeesTimer\target\EmployeesTimer-1.0-SNAPSHOT.jar.xml) not found.

Here is The 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>com.unilever</groupId>
    <artifactId>EmployeesTimer</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>ejb</packaging>

    <name>EmployeesTimer</name>

    <properties>
        <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-bundle</artifactId>
            <version>1.8</version>
        </dependency>

        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>6.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-mapper-asl</artifactId>
            <version>1.9.2</version>
        </dependency>

        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-core-asl</artifactId>
            <version>1.9.2</version>
        </dependency>

        <!-- slf4j Logger -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.7</version>
        </dependency>    

        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.7</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                    <compilerArguments>
                        <endorseddirs>${endorsed.dir}</endorseddirs>
                    </compilerArguments>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-ejb-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <ejbVersion>3.1</ejbVersion>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.1</version>
                <executions>
                    <execution>
                        <phase>validate</phase>
                        <goals>
                            <goal>copy</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${endorsed.dir}</outputDirectory>
                            <silent>true</silent>
                            <artifactItems>
                                <artifactItem>
                                    <groupId>javax</groupId>
                                    <artifactId>javaee-endorsed-api</artifactId>
                                    <version>6.0</version>
                                    <type>jar</type>
                                </artifactItem>
                            </artifactItems>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>unknown-jars-temp-repo</id>
            <name>A temporary repository created by NetBeans for libraries and jars it could not identify. Please replace the dependencies in this repository with correct ones and delete this repository.</name>
            <url>file:${project.basedir}/lib</url>
        </repository>
        <repository>
            <id>m2.dev.java.net</id>
            <url>http://download.java.net/maven/2</url>
            <layout>default</layout>
        </repository>
        <repository>  
            <id>prime-repo</id>  
            <name>PrimeFaces Maven Repository</name>  
            <url>http://repository.primefaces.org</url>  
            <layout>default</layout>  
        </repository>  
    </repositories>
</project>

I confirm that I have 2 simple ejb

@Stateless public class EmployeesFacade {} 
@Singleton public class TimerService { 
@EJB EmployeesFacade emloyeesFacade;
} 

Here is the code:

First @singleton ejb bean

package com.employeestimer.services;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.unilever.employeestimer.enums.ConnectionEnum;
import com.unilever.employeestimer.exceptions.BusinessException;
import java.io.IOException;
import javax.ejb.EJB;
import javax.ejb.Schedule;
import javax.ejb.Singleton;
import javax.naming.NamingException;
import javax.ws.rs.core.MediaType;
import org.codehaus.jackson.JsonProcessingException;
import org.slf4j.LoggerFactory;


@Singleton
public class TimerService {
    static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(TimerService.class);

    @EJB
    EmployeesFacade  emloyeesFacade;

    private final static String U_ENGAGE_URL = "http://..../webresources/employees/update";

    @Schedule(second="*", minute="*/1",hour="*", persistent=false)
    public void doWork() throws JsonProcessingException, IOException, NamingException{
       try{
            String input = emloyeesFacade.getUsersData(ConnectionEnum.USERNAME.getCode(), ConnectionEnum.PASSWORD.getCode());
            consumeRESTfulWebService(input);            
       }catch(BusinessException e){
           LOGGER.error("",e);
       }

    }

    private void consumeRESTfulWebService(String input){             
       try {
            LOGGER.debug("input = " + input);
            Client client = Client.create();
            WebResource webResource = client.resource(U_ENGAGE_URL);
            ClientResponse response = webResource.type(MediaType.TEXT_PLAIN).post(ClientResponse.class, input);
            if (response.getStatus() != ClientResponse.Status.NO_CONTENT.getStatusCode()) {
                throw new RuntimeException("Failed : HTTP error code : "
                     + response.getStatus());
            }
            LOGGER.debug("Output from Server .... \n");
        } catch (Exception e) {
            LOGGER.error("",e);
    }
    }
}

and here is the Facade bean:

package com.employeestimer.services;

import com.employeestimer.beans.EmployeeData;
import com.employeestimer.enums.ConfigurationsEnum;
import com.employeestimer.enums.ConnectionEnum;
import com.employeestimer.exceptions.BusinessException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import javax.ejb.Stateless;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.Control;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import javax.naming.ldap.PagedResultsControl;
import javax.naming.ldap.PagedResultsResponseControl;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.ObjectWriter;
import org.slf4j.LoggerFactory;


@Stateless
public class EmployeesFacade {

    static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(EmployeesFacade.class);

    public String getLDAPConnectionType() {
        return ConfigurationsEnum.LDAP_Connection_Type.getCode();
    }

    public String getDomain() {
        return ConfigurationsEnum.DOMAIN.getCode();
    }

    public String getLDAPIP() {
        return ConfigurationsEnum.LDAP_IP.getCode();
    }

    public String getLDAPPort() {
        return ConfigurationsEnum.LDAP_PORT.getCode();
    }

    public String getLDAPBase() {
        return ConfigurationsEnum.LDAP_BASE.getCode();
    }

    private LdapContext getContext(String username, String password) throws BusinessException, NamingException {
        Hashtable env = new Hashtable();
        if (getDomain() == null || getLDAPConnectionType() == null
                || getLDAPIP() == null || getLDAPPort() == null) {
            throw new BusinessException("error_general");
        }
        String domain = getDomain();
        String url = getLDAPConnectionType() + "://" + getLDAPIP() + ":" + getLDAPPort();
        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        env.put(Context.PROVIDER_URL, url);
        env.put(Context.SECURITY_AUTHENTICATION, "simple");
        env.put(Context.REFERRAL, "follow");
        if (!username.contains("@")) {
            username = username + "@" + domain;
        }
        env.put(Context.SECURITY_PRINCIPAL, username);
        env.put(Context.SECURITY_CREDENTIALS, password);
        return new InitialLdapContext(env, null);
    }

    public String getUsersData(String username, String password) throws BusinessException, JsonProcessingException, IOException, NamingException {
        List<EmployeeData> employeelist = new ArrayList<EmployeeData>();
        EmployeeData employee;
        String json = "";
        try {
            LdapContext context = getContext(username, password);
            SearchControls constraints = new SearchControls();
            constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
            String[] attrIDs = {"mail"};    //, "sn", "cn", "c", "l"};
            constraints.setReturningAttributes(attrIDs);
            // Activate paged results
            int pageSize = Integer.parseInt(ConnectionEnum.PAGESIZE.getCode());
            byte[] cookie = null;
            context.setRequestControls(new Control[]{new PagedResultsControl(pageSize,
                Control.NONCRITICAL)});
            int total;
            NamingEnumeration<SearchResult> result = null;
            do {
                /* perform the search */
                result = context.search(getLDAPBase(), "(&(objectClass=User)(c=EG))", constraints);
                /* for each entry print out name + all attrs and values */
                while (result != null && result.hasMore()) {
                    SearchResult entry = (SearchResult) result.next();
                    employee = new EmployeeData();
                    Attribute attribute;

                    if (entry.getAttributes() != null) {
                        if (entry.getAttributes().get("mail") != null) {
                            attribute = entry.getAttributes().get("mail");
                            employee.setEmail(attribute != null ? attribute.toString().replace("mail: ", "") : "");
                            employeelist.add(employee);
                        }
                    }
            }
                // Examine the paged results control response
                Control[] controls = context.getResponseControls();
                if (controls != null) {
                    for (int i = 0; i < controls.length; i++) {
                        if (controls[i] instanceof PagedResultsResponseControl) {
                            PagedResultsResponseControl prrc = (PagedResultsResponseControl) controls[i];
                            total = prrc.getResultSize();
                            if (total != 0) {
                                LOGGER.debug("***************** END-OF-PAGE " + "(total : " + total + ") *****************\n");
                            } else {
                                LOGGER.debug("***************** END-OF-PAGE " + "(Page no. " + i + ") ***************\n");
                            }
                            cookie = prrc.getCookie();
                        }
                    }
                } else {
                    LOGGER.debug("No controls were sent from the server");
                }
                // Re-activate paged results
                context.setRequestControls(new Control[]{new PagedResultsControl(
                    pageSize, cookie, Control.CRITICAL)});
            } while (cookie != null);
            //result.close();
            context.close();
            ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
            json = ow.writeValueAsString(employeelist);
            LOGGER.debug("\n \n \n ************* \n ************* \n ************* \n \n THE SIZE = " + employeelist.size() + "\n \n ************* \n ************* \n ************* \n \n \n");
        } catch (NamingException ex) {
            String detailmessage = ex.getExplanation();
            if (detailmessage.contains(" 32 ")) {
                // User not Found
                throw new BusinessException("error_invalidUser");
            } else if (detailmessage.contains(" 49 ")) {
                if (detailmessage.contains(" 775 ") || detailmessage.contains(" 701 ") || detailmessage.contains(" 533 ")) {
                    //Invalid Account
                    throw new BusinessException("error_invalidAccount");
                } else {
                    //Invalid Username or password
                    throw new BusinessException("error_invalidUsernamePassword");
                }
            } else {
                LOGGER.error("error_general", ex);
                throw new BusinessException("error_general");
            }
        }
        return json;
    }
}
Mariam A. Moustafa
  • 165
  • 1
  • 2
  • 14

1 Answers1

2

I don't see a problem with your setup. If you really have some class annotated with @Singleton or @Stateless inside this project, this should work.

But one important point is that if you have any dependencies which are not available in the libs of Glassfish, you have to package them with your application which is not possible with EJB/JAR packaging. You have to package it as a WAR or EAR file.

For a quick start, try the following:

Change

<packaging>ejb</packaging>

to

<packaging>war</packaging>

and change

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-ejb-plugin</artifactId>
            <version>2.3</version>
            <configuration>
                <ejbVersion>3.1</ejbVersion>
            </configuration>
        </plugin>

to

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <version>2.1.1</version>
            <configuration>
                <failOnMissingWebXml>false</failOnMissingWebXml>
            </configuration>
        </plugin>

If you want to package it as an EAR, you can use the maven-ear-plugin.

See also:

Community
  • 1
  • 1
unwichtich
  • 13,712
  • 4
  • 53
  • 66
  • dear unwichtich, when I try your suggestion, it works fine and Glassfish deploys the war file successfully! But what about the EJB module? how can I deploy within GlassFish? what is the cause for that problem?!!! I confirm that I have 2 simple ejb @ Stateless public class EmployeesFacade {} @ Singleton public class TimerService { @ EJB EmployeesFacade emloyeesFacade; } – Mariam A. Moustafa Jun 24 '15 at 08:21
  • 1
    See the third point in the error message, there may be another error message inside your `server.log`. – unwichtich Jun 24 '15 at 08:31
  • the server.log has no exceptions! also when I run the verifier tool for the WAR, I got the same result...Verifier output unparsable Verifier output (C:\Users\Mariam.Moustafa\Documents\NetBeansProjects\web\EmployeesTimer\target\EmployeesTimer-1.0-SNAPSHOT.war.xml) not found. – Mariam A. Moustafa Jun 24 '15 at 09:51
  • I am using EJB 3.0 why *.XML files is required!! – Mariam A. Moustafa Jun 24 '15 at 09:52
  • 1
    I have tested a project with your `pom.xml` and a blank `@Singleton` and it works for me...I don't use the Glassfish Verifier Tool but I guess you can ignore that. Maybe you can add the complete source of your beans (with imports) to the question (or put it on GitHub or similar). – unwichtich Jun 24 '15 at 13:42
  • 1
    If I comment out the stuff which required additional classes like `ConnectionEnum`, your code works for and deploys fine. To make sure the problem is somewhere in your code, your could comment out everything in your classes except the `@Stateless` and `@Singleton` annotations (just an empty class, only the annotations) and see if that works. – unwichtich Jun 25 '15 at 11:16