This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

Bug 179698 - EJB Module project: remote interfaces & implementations in the same jar
Summary: EJB Module project: remote interfaces & implementations in the same jar
Status: RESOLVED FIXED
Alias: None
Product: javaee
Classification: Unclassified
Component: EJB Project (show other bugs)
Version: 6.x
Hardware: PC All
: P2 normal with 2 votes (vote)
Assignee: David Konecny
URL:
Keywords:
Depends on:
Blocks: 182220
  Show dependency tree
 
Reported: 2010-01-20 03:52 UTC by puce
Modified: 2010-06-27 22:15 UTC (History)
1 user (show)

See Also:
Issue Type: DEFECT
Exception Reporter:


Attachments
Patch to make this work in Maven (1.57 KB, patch)
2010-03-17 14:55 UTC, Petr Jiricka
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description puce 2010-01-20 03:52:55 UTC
When adding a remote Session bean to an "EJB Module" project, the remote 
interface gets added to the same project - and thus to the same jar.

Since the jar with the remote interface needs to be deployed to the client, 
like this the client would also get the whole implementation of the EJB!

IMHO there's hardly a scenario where such a configuration would be useful. 

It's not only a question of the jar size! If the EJBs are closed source, the 
clients would get access to the class files and could decompile them!

A solution could be to introduce a new project type (eg. a "Remote EJB Module") which accompanies an "EJB Module" project.

This "Remote EJB Module" project should:
 - have access to jars of the Java EE application server, configured in the "Enterprise Application"/ "EJB Module" project (eg. the Glassfish jars)
 - contain all the remote interfaces along with the DTOs, Excpetions and other 
classes referenced by the remote interfaces, which need to be deployed to the 
client along with the remote interfaces (or have a dependency to libraries/ 
projects/ jars which provide those classes)

The "EJB Module" project should:
 - have a dependency to this "Remote EJB Module" project, to allow 
implementations of the remote interface (classpath)
 - have an option to configure this "companion" project
 - create the remote interface in its configured "companion" project, when a 
new session beans is added. If no "companion" project is configured yet, there 
should be the 2 options:
  --  specify one
  --  create a new  "companion" project

Eg. an "Enterprise Application Client" project only needs a dependency to the 
"Remote EJB Module" project and not one to the "EJB Module" project.

Since IMHO it's almost always a bad idea to have the remote interface and the implementation in the same jar, I mark this issue as DEFECT.
Comment 1 David Konecny 2010-01-27 20:04:55 UTC
puce, I agree that Remote interface does not make much sense in project containing EJB implementation. Here is an idea for simple enhancement (along the lines of what you are writing):

- let's enhance New EJB wizard so that when "Create Interface: Remote" is ticked an additional combo box is shown next to it and the combo would list all currently opened projects and would allow user to select into which project remote interface should be created. The package name would be the same as for EJB implementation class. The combo box could have one extra value named "Create New Project" and that option would open standard New Project wizard.
This enhancement (while simple to implement) would allow users to place remote interfaces into an alternative project and would automatically add such a project to current project's classpath (if it is not there already). Java EE API library could be automatically added to project's classpath to make remote interface compilable. Target project for remote interface can be any project which output is JAR file (most commonly J2SE Class Library Project).

What do you think?

All this can be done by hand as you probably know: just create a new J2SE Class Library project and add Java EE 6 API library to its classpath, add that project to compilation classpath of your EJB project and use move refactoring to move remote interfaces to this new project. That should work as expected.
Comment 2 David Konecny 2010-02-28 21:53:18 UTC
New Session EJB wizard allow to choose a project for Remote Interface generation. It is very basic but does the job.
d2209a4dec11
Comment 3 puce 2010-03-01 03:20:21 UTC
Hi David,

sorry for the late answer.

I think your proposed solution is fine and simpler (doesn't introduce a new project type).

I will try it once it is available in a stable version of the IDE.
Comment 4 Petr Jiricka 2010-03-17 14:55:36 UTC
Created attachment 95313 [details]
Patch to make this work in Maven

Still does not work in Maven for me, as I can not choose a Maven project from the list. I am attaching a patch that improves this for Maven, although it's not 100% correct - it lists some projects (such as Maven webapps) that should be disallowed.
Comment 5 David Konecny 2010-03-17 19:11:00 UTC
Feel free to go ahead and push your patch Petr. It looks sort of OK. The reason for that condition is that for example Web Applications are not listed as destination for remote interface - Web Application produces WAR file and placing WAR file on project's classpath does not make sense. I do not know how you going to prevent that in Maven projects case, but on the other hand it is P4 issue.
Comment 6 Petr Jiricka 2010-03-17 19:48:32 UTC
That was exactly my thinking. I discussed with Dafe and there is no simple way to find packaging type for Maven projects without introducing a dependency on the Maven module. Pushed: http://hg.netbeans.org/web-main/rev/53bb3df532df
Comment 7 puce 2010-06-23 18:58:10 UTC
Hi David,

I could now test this feature in NetBeans 6.9.

It seems to work fine with Ant, but with Maven, the generated application cannot be loaded by Glassfish. Here is the error message, where "test/service/MyServiceBeanRemote" is the remote interface in a separate jar:

----------------------- 
WARNING: Error in annotation processing: java.lang.NoClassDefFoundError: test/service/MyServiceBeanRemote
SEVERE: Exception while deploying the app
java.lang.IllegalArgumentException: Invalid ejb jar [TechnologyTestEA-ejb-1.0-SNAPSHOT.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.
        at com.sun.enterprise.deployment.util.EjbBundleValidator.accept(EjbBundleValidator.java:72)
        at com.sun.enterprise.deployment.util.ApplicationValidator.accept(ApplicationValidator.java:124)
        at com.sun.enterprise.deployment.EjbBundleDescriptor.visit(EjbBundleDescriptor.java:722)
        at com.sun.enterprise.deployment.Application.visit(Application.java:1744)
        at com.sun.enterprise.deployment.archivist.ApplicationArchivist.validate(ApplicationArchivist.java:774)
        at com.sun.enterprise.deployment.archivist.ApplicationArchivist.openWith(ApplicationArchivist.java:253)
        at com.sun.enterprise.deployment.archivist.ApplicationFactory.openWith(ApplicationFactory.java:222)
        at org.glassfish.javaee.core.deployment.DolProvider.load(DolProvider.java:152)
        at org.glassfish.javaee.core.deployment.DolProvider.load(DolProvider.java:79)
        at com.sun.enterprise.v3.server.ApplicationLifecycle.loadDeployer(ApplicationLifecycle.java:612)
        at com.sun.enterprise.v3.server.ApplicationLifecycle.setupContainerInfos(ApplicationLifecycle.java:554)
        at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:262)
        at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:183)
        at org.glassfish.deployment.admin.DeployCommand.execute(DeployCommand.java:272)
        at com.sun.enterprise.v3.admin.CommandRunnerImpl$1.execute(CommandRunnerImpl.java:305)
        at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:320)
        at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:1176)
        at com.sun.enterprise.v3.admin.CommandRunnerImpl.access$900(CommandRunnerImpl.java:83)
        at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1235)
        at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1224)
        at com.sun.enterprise.v3.admin.AdminAdapter.doCommand(AdminAdapter.java:365)
        at com.sun.enterprise.v3.admin.AdminAdapter.service(AdminAdapter.java:204)
        at com.sun.grizzly.tcp.http11.GrizzlyAdapter.service(GrizzlyAdapter.java:166)
        at com.sun.enterprise.v3.server.HK2Dispatcher.dispath(HK2Dispatcher.java:100)
        at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:245)
        at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:791)
        at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:693)
        at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:954)
        at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:170)
        at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:135)
        at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:102)
        at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:88)
        at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76)
        at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:53)
        at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:57)
        at com.sun.grizzly.ContextTask.run(ContextTask.java:69)
        at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:330)
        at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:309)
        at java.lang.Thread.run(Thread.java:619)
----------------------- 
Creating the classpath entry in the manifest file of the ejb-module did not help:
           <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-ejb-plugin</artifactId>
                <version>2.1</version>
                <configuration>
                    <ejbVersion>3.1</ejbVersion>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
---

Another issue is, that the generated dependency to javaee-api in the separate remote library doesn't have:
<scope>provided</scope>
Comment 8 David Konecny 2010-06-27 22:15:53 UTC
What you are experiencing is maven bug 186223.

> Another issue is, that the generated dependency to javaee-api in the separate
> remote library doesn't have: <scope>provided</scope>

This works for me (on latest dev build). I think that Petr Jiricka fixed that recently.

If something else does not work please file a new issue directly for javaee/maven. Thanks!