title: IllegalArgumentException: Invalid ejb jar [HelloEJB]: it contains zero ejb.
body: <p>While <a href="https://stackoverflow.com/questions/25828542/how-to-create-a-remote-session-ejb-from-a-client/25829907#25829907">the previous sample client</a> from the <a href="https://netbeans.org/kb/docs/javaee/entappclient.html" rel="nofollow noreferrer">Creating and Running an Application Client on the GlassFish Server</a> tutorial runs correctly, I'm going through the process again to clarify the procedures for better understanding.  Specifically, to manually deploy the bean to Glassfish from the CLI rather than from the IDE.  The session bean is <code>@stateless</code> and implements <code>@remote</code>.  This version of Glassfish shipped with Netbeans.</p>
  
  <p>The bean is an "EJB module" with the library API <code>HelloLibrary</code> <a href="https://netbeans.org/kb/docs/javaee/entappclient.html#Exercise_30" rel="nofollow noreferrer">included as a "library" so that it's on the module's classpath</a>.  These are separate, unrelated projects.  When the EJB module <code>HelloEJB</code> is deployed, this <code>@remote</code> library API is somehow deployed to Glassfish (at least I infer that to be the case, as it's required by the bean).  It's almost, but not exactly, as in the tutorial.  The exact steps in the tutorial didn't work for me, I had to put the bean in an independent EJB module rather than an Enterprise Application with an EJB module.  </p>
  
  <p>The salient point being that <a href="https://stackoverflow.com/questions/25828542/how-to-create-a-remote-session-ejb-from-a-client/25829907#25829907">everything runs from within the IDE</a> -- now trying to deploy and run the bean from outside of the IDE.</p>
  
  <p>From the IDE, right clicking on the bean will deploy it Glassfish:</p>
  
  <pre><code>thufir@dur:~$ 
  thufir@dur:~$ glassfish-4.1/glassfish/bin/asadmin list-applications
  Nothing to list.
  No applications are deployed to this target server.
  Command list-applications executed successfully.
  thufir@dur:~$ 
  thufir@dur:~$ glassfish-4.1/glassfish/bin/asadmin list-applications
  HelloEJB  &lt;ejb&gt;  
  Command list-applications executed successfully.
  thufir@dur:~$ 
  </code></pre>
  
  <p>However, my attempts to manually deploy the JAR fail, despite the <code>@remote</code> interface library being in the Glassfish <code>/lib</code> directory:</p>
  
  <pre><code>thufir@dur:~$ 
  thufir@dur:~$ glassfish-4.1/glassfish/bin/asadmin list-applications
  HelloEJB  &lt;ejb&gt;  
  Command list-applications executed successfully.
  thufir@dur:~$ 
  thufir@dur:~$ glassfish-4.1/glassfish/bin/asadmin undeploy HelloEJB
  Command undeploy executed successfully.
  thufir@dur:~$ 
  thufir@dur:~$ glassfish-4.1/glassfish/bin/asadmin list-applications
  Nothing to list.
  No applications are deployed to this target server.
  Command list-applications executed successfully.
  thufir@dur:~$ 
  thufir@dur:~$ glassfish-4.1/glassfish/bin/asadmin deploy /home/thufir/NetBeansProjects/HelloEJB/dist/HelloEJB.jar 
  remote failure: Error occurred during deployment: Exception while deploying the app [HelloEJB] : Invalid ejb jar [HelloEJB]: 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.
  Command deploy failed.
  thufir@dur:~$ 
  thufir@dur:~$ ll glassfish-4.1/glassfish/lib/HelloLibrary.jar 
  -rw-rw-r-- 1 thufir thufir 789 Sep 22 01:41 glassfish-4.1/glassfish/lib/HelloLibrary.jar
  thufir@dur:~$ 
  </code></pre>
  
  <p>the bean:</p>
  
  <pre><code>package hello;
  
  import javax.ejb.Stateless;
  
  @Stateless
  public class HelloBean implements HelloBeanRemote {
  
      @Override
      public String hi() {
          return "hello world";
      }
  
      @Override
      public String bye() {
          return "goodbye";
      }
  
  }
  </code></pre>
  
  <p>the interface:</p>
  
  <pre><code>package hello;
  
  import javax.ejb.Remote;
  
  @Remote
  public interface HelloBeanRemote {
  
      public String hi();
  
      public String bye();
  }
  </code></pre>
  
  <p>server log:</p>
  
  <pre><code>thufir@dur:~$ 
  thufir@dur:~$ tail glassfish-4.1/glassfish/domains/domain1/logs/server.log -n 99
      at com.sun.enterprise.loader.ASURLClassLoader.findClassData(ASURLClassLoader.java:865)
      at com.sun.enterprise.loader.ASURLClassLoader.findClass(ASURLClassLoader.java:742)
      at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
      at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
      ... 81 more
  ]]
  
  [2014-09-22T01:30:22.299-0700] [glassfish 4.1] [SEVERE] [] [javax.enterprise.system.core] [tid: _ThreadID=40 _ThreadName=admin-listener(3)] [timeMillis: 1411374622299] [levelValue: 1000] [[
    Exception while deploying the app [HelloEJB]]]
  
  [2014-09-22T01:30:22.300-0700] [glassfish 4.1] [SEVERE] [NCLS-CORE-00026] [javax.enterprise.system.core] [tid: _ThreadID=40 _ThreadName=admin-listener(3)] [timeMillis: 1411374622300] [levelValue: 1000] [[
    Exception during lifecycle processing
  java.lang.IllegalArgumentException: Invalid ejb jar [HelloEJB]: 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.
      at org.glassfish.ejb.deployment.util.EjbBundleValidator.accept(EjbBundleValidator.java:147)
      at org.glassfish.ejb.deployment.util.EjbBundleValidator.accept(EjbBundleValidator.java:112)
      at com.sun.enterprise.deployment.BundleDescriptor.visit(BundleDescriptor.java:625)
      at org.glassfish.ejb.deployment.descriptor.EjbBundleDescriptorImpl.visit(EjbBundleDescriptorImpl.java:757)
      at com.sun.enterprise.deployment.util.ApplicationValidator.accept(ApplicationValidator.java:121)
      at com.sun.enterprise.deployment.BundleDescriptor.visit(BundleDescriptor.java:625)
      at com.sun.enterprise.deployment.archivist.ApplicationFactory.openArchive(ApplicationFactory.java:190)
      at org.glassfish.javaee.core.deployment.DolProvider.processDOL(DolProvider.java:203)
      at org.glassfish.javaee.core.deployment.DolProvider.load(DolProvider.java:227)
      at org.glassfish.javaee.core.deployment.DolProvider.load(DolProvider.java:96)
      at com.sun.enterprise.v3.server.ApplicationLifecycle.loadDeployer(ApplicationLifecycle.java:881)
      at com.sun.enterprise.v3.server.ApplicationLifecycle.setupContainerInfos(ApplicationLifecycle.java:821)
      at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:377)
      at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:219)
      at org.glassfish.deployment.admin.DeployCommand.execute(DeployCommand.java:491)
      at com.sun.enterprise.v3.admin.CommandRunnerImpl$2$1.run(CommandRunnerImpl.java:539)
      at com.sun.enterprise.v3.admin.CommandRunnerImpl$2$1.run(CommandRunnerImpl.java:535)
      at java.security.AccessController.doPrivileged(Native Method)
      at javax.security.auth.Subject.doAs(Subject.java:356)
      at com.sun.enterprise.v3.admin.CommandRunnerImpl$2.execute(CommandRunnerImpl.java:534)
      at com.sun.enterprise.v3.admin.CommandRunnerImpl$3.run(CommandRunnerImpl.java:565)
      at com.sun.enterprise.v3.admin.CommandRunnerImpl$3.run(CommandRunnerImpl.java:557)
      at java.security.AccessController.doPrivileged(Native Method)
      at javax.security.auth.Subject.doAs(Subject.java:356)
      at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:556)
      at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:1464)
      at com.sun.enterprise.v3.admin.CommandRunnerImpl.access$1300(CommandRunnerImpl.java:109)
      at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1846)
      at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1722)
      at org.glassfish.admin.rest.resources.admin.CommandResource.executeCommand(CommandResource.java:404)
      at org.glassfish.admin.rest.resources.admin.CommandResource.execCommandSimpInMultOut(CommandResource.java:234)
      at sun.reflect.GeneratedMethodAccessor481.invoke(Unknown Source)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:606)
      at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(ResourceMethodInvocationHandlerFactory.java:81)
      at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:151)
      at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:171)
      at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:152)
      at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:104)
      at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:387)
      at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:331)
      at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:103)
      at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:271)
      at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
      at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
      at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
      at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
      at org.glassfish.jersey.internal.Errors.process(Errors.java:267)
      at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:297)
      at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:254)
      at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1028)
      at org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer.service(GrizzlyHttpContainer.java:365)
      at org.glassfish.admin.rest.adapter.JerseyContainerCommandService$3.service(JerseyContainerCommandService.java:173)
      at org.glassfish.admin.rest.adapter.RestAdapter.service(RestAdapter.java:179)
      at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:459)
      at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:167)
      at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:201)
      at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:175)
      at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235)
      at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
      at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284)
      at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
      at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
      at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
      at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
      at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:561)
      at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
      at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
      at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
      at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
      at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:565)
      at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:545)
      at java.lang.Thread.run(Thread.java:744)
  ]]
  
  [2014-09-22T01:30:22.304-0700] [glassfish 4.1] [SEVERE] [] [javax.enterprise.system.core] [tid: _ThreadID=40 _ThreadName=admin-listener(3)] [timeMillis: 1411374622304] [levelValue: 1000] [[
    Exception while deploying the app [HelloEJB] : Invalid ejb jar [HelloEJB]: 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.]]
  
  thufir@dur:~$ 
  </code></pre>
  
  <p>Interestingly enough, Netbeans doesn't copy the <code>@remote</code> interface library, <code>HelloLibrary</code>, to the Glassfish <code>lib</code> directory.  How it's able to deploy the bean is a bit of a mystery -- that being said, I just want to be able to deploy it.</p>