Incorrect JNDI name used for local EJB
GlassFish Version (and build number)
Failed with: 8.0.0-M12 7.1.0-SNAPSHOT 7.0.25
Passed with: 6.2.5
Problem Description
When upgrading Arquillian GF project I have noticed some weird bug - one test was failing. When I remove the explicit class in Local annotation, the test fails with GF7.1 in a standalone JAR module deployed by arquillian. With some extreme logging I have found that the bean is deployed under
Deployment to 6.2.5, 7.0.25, 7.1.0-SNAPSHOT and 8.0.0-M12:
java:global/test-55dfc3ae-4577-4ac2-ba97-bdb606c75d74/LocalInterfaceEJBBean,
java:global/test-55dfc3ae-4577-4ac2-ba97-bdb606c75d74/LocalInterfaceEJBBean!org.omnifaces.arquillian.container.glassfish.embedded.app.LocalInterfaceEJB,
On 6.2.5 the test succeeded, while on versions 7.0+ @EJB annotation fails to find
lookup(name=
java:global/test-55dfc3ae-4577-4ac2-ba97-bdb606c75d74/LocalInterfaceEJB level=0)
@EJB
private LocalInterfaceEJB bean;
...
@Stateless
@Local(LocalInterfaceEJB.class)
public class LocalInterfaceEJBBean implements LocalInterfaceEJB {
Workaround:
When I added the name to the Stateless annotation, test passed:
@Stateless(name = "LocalInterfaceEJB")
@Local(LocalInterfaceEJB.class)
public class LocalInterfaceEJBBean implements LocalInterfaceEJB {
Steps to reproduce
See IntegrationJarTestCase in https://github.com/OmniFish-EE/arquillian-container-glassfish
Could be related to #25219
GF should use the interface name as the JNDI name, not bean class name.
Why this should be?
See IntegrationJarTestCase in https://github.com/OmniFish-EE/arquillian-container-glassfish
Running it as is (5a2781d) - pass. With
--- a/glassfish-embedded/src/test/java/org/omnifaces/arquillian/container/glassfish/embedded/app/LocalInterfaceEJBBean.java
+++ b/glassfish-embedded/src/test/java/org/omnifaces/arquillian/container/glassfish/embedded/app/LocalInterfaceEJBBean.java
@@ -66,7 +66,7 @@ import jakarta.ejb.Stateless;
* @version $Revision: $
*/
@Stateless
-@Local(LocalInterfaceEJB.class)
+//@Local(LocalInterfaceEJB.class)
public class LocalInterfaceEJBBean implements LocalInterfaceEJB {
public String getName() {
return new NameProvider().getName();
also - pass.
Please help me see this issue.
Because you executed it against GF 6.2.5, am I right? Also in 5a2781d47f479563cf5378fd44ace58d56480a98 @arjan disabled this test. I was already looking at it in parallel, however as I am working in parallel on GF 7.1.0-SNAPSHOT and TCK and Arquillian I did not push my arquillian and TCK changes yet.
@pzygielo I finally had some time to return to this, so I updated the description to make it clear, sorry, I hope you did not burn too much time with it yet. I confused even myself with that, now I see why:
I am thinking about it ...
- It sounds logical to me that when I declare a business interface to hide all the implementation details, so even the JNDI name would use the interface name.
- However, if I would have more than one implementation of such interface, I would have a collision in JNDI.
- Then it is more logical to use unique impl name. But then the injection point still has no idea what to inject, then the failure is ok. How could it work in 6.2.5?
- Revert. So then we could use the interface name and if there would be a collision, we would refuse the deployment.
- All in all I think the test should pass but it doesn't. I will create a PR for Arquillian, then we can resolve it somehow ...
https://jakarta.ee/specifications/enterprise-beans/4.0/apidocs/jakarta/ejb/stateless#name--
Stateless.name:public abstract String nameThe
ejb-namefor this bean. Defaults to the unqualified name of the stateless session bean class.
Then @Local cannot be injected, right? It cannot be found, because the injection point knows just the interface.
I can't confirm.
Using
- 7.0.25, JDK 21
- 8.0.0-M12, JDK 21
I'm seeing EJBs correctly injected into servlet, with explicit @Local on interface, without @Local on interface and with @Local specifying interface on implementing bean.
I'm unable to guess what is your case.
Do you see any Exception during lifecycle processing?
Can you extract https://stackoverflow.com/help/minimal-reproducible-example?
Hi,
Can you extract https://stackoverflow.com/help/minimal-reproducible-example?
It should be this test:
https://github.com/OmniFish-EE/arquillian-container-glassfish/blob/main/glassfish-embedded/src/test/java/org/omnifaces/arquillian/container/glassfish/embedded/app/IntegrationJarTestCase.java
Code:
public interface LocalInterfaceEJB {
public String getName();
}
@Stateless
@Local(LocalInterfaceEJB.class)
public class LocalInterfaceEJBBean implements LocalInterfaceEJB {
public String getName() {
return new NameProvider().getName();
}
}
@RunWith(Arquillian.class)
public class IntegrationJarTestCase {
@Deployment
public static JavaArchive createDeployment() throws Exception {
return create(JavaArchive.class)
.addClasses(
LocalInterfaceEJB.class,
LocalInterfaceEJBBean.class);
}
@EJB
private LocalInterfaceEJB bean;
@Test
public void shouldBeAbleToInjectEJBAsInstanceVariable() throws Exception {
assertNotNull("Verify that the Bean has been injected", bean);
assertEquals("Arquillian", bean.getName());
}
}
Can you extract https://stackoverflow.com/help/minimal-reproducible-example?
I planned to add and provide reproduction steps, but then thought it's unnecessary to write that as this is so obvious. Apparently I was wrong. 😞
It should be this test:
https://github.com/OmniFish-EE/arquillian-container-glassfish/blob/main/glassfish-embedded/src/test/java/org/omnifaces/arquillian/container/glassfish/embedded/app/IntegrationJarTestCase.java
Using b5db9f90bf2eee6d50f57cb0ecf097fc7c70f1df.
Using JDK 21.
Using: mvn clean verify -f glassfish-embedded -Dtest=IntegrationJarTestCase
Getting:
[WARNING] Tests run: 1, Failures: 0, Errors: 0, Skipped: 1
Applying
diff --git a/glassfish-embedded/src/test/java/org/omnifaces/arquillian/container/glassfish/embedded/app/IntegrationJarTestCase.java b/glassfish-embedded/src/test/java/org/omnifaces/arquillian/container/glassfish/embedded/app/IntegrationJarTestCase.java
index f386395..dc0a9a6 100644
--- a/glassfish-embedded/src/test/java/org/omnifaces/arquillian/container/glassfish/embedded/app/IntegrationJarTestCase.java
+++ b/glassfish-embedded/src/test/java/org/omnifaces/arquillian/container/glassfish/embedded/app/IntegrationJarTestCase.java
@@ -90,7 +90,7 @@ public class IntegrationJarTestCase {
private LocalInterfaceEJB bean;
@Test
- @Ignore("Look at later")
+ //@Ignore("Look at later")
public void shouldBeAbleToInjectEJBAsInstanceVariable() throws Exception {
assertNotNull("Verify that the Bean has been injected", bean);
Using: mvn clean verify -f glassfish-embedded -Dtest=IntegrationJarTestCase
Getting:
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
I still don't see the issue. Is it bad that the test passed? Is it good?
I still don't see the issue. Is it bad that the test passed? Is it good?
The test at some point (using GlassFish 7.0.25) was really eager to fail every time. It kept complaining about the EJB not being able to be injected. If the issue magically fixed itself I guess we can close it. Must have been a fluke of some sort then.
The only strange thing remaining is that on both my system and at that of @dmatej we really witnessed it failing.
If the issue magically fixed itself I guess we can close it.
I suspect the magic to be https://github.com/OmniFish-EE/arquillian-container-glassfish/commit/c294a7188b347fd1b0d3b2fc32bee42aeb0fbac2
I can massage https://github.com/OmniFish-EE/arquillian-container-glassfish/
diff --git a/glassfish-embedded/src/test/java/org/omnifaces/arquillian/container/glassfish/embedded/app/IntegrationJarTestCase.java b/glassfish-embedded/src/test/java/org/omnifaces/arquillian/container/glassfish/embedded/app/IntegrationJarTestCase.java
index f386395..3f862b3 100644
--- a/glassfish-embedded/src/test/java/org/omnifaces/arquillian/container/glassfish/embedded/app/IntegrationJarTestCase.java
+++ b/glassfish-embedded/src/test/java/org/omnifaces/arquillian/container/glassfish/embedded/app/IntegrationJarTestCase.java
@@ -90,7 +90,6 @@ public class IntegrationJarTestCase {
private LocalInterfaceEJB bean;
@Test
- @Ignore("Look at later")
public void shouldBeAbleToInjectEJBAsInstanceVariable() throws Exception {
assertNotNull("Verify that the Bean has been injected", bean);
diff --git a/glassfish-embedded/src/test/java/org/omnifaces/arquillian/container/glassfish/embedded/app/LocalInterfaceEJBBean.java b/glassfish-embedded/src/test/java/org/omnifaces/arquillian/container/glassfish/embedded/app/LocalInterfaceEJBBean.java
index a6cdd56..c42bb32 100644
--- a/glassfish-embedded/src/test/java/org/omnifaces/arquillian/container/glassfish/embedded/app/LocalInterfaceEJBBean.java
+++ b/glassfish-embedded/src/test/java/org/omnifaces/arquillian/container/glassfish/embedded/app/LocalInterfaceEJBBean.java
@@ -66,7 +66,7 @@ import jakarta.ejb.Stateless;
* @version $Revision: $
*/
// FIXME: The name is required - probably a bug in GlassFish
-@Stateless(name = "LocalInterfaceEJB")
+@Stateless//(name = "LocalInterfaceEJB")
@Local
public class LocalInterfaceEJBBean implements LocalInterfaceEJB {
@Override
to make IntegrationJarTestCase fail
Is that the case to investigate?
Is that the case to investigate?
yeah, so basically the state as it was before I first ignored the test. That should be the java code I printed above:
public interface LocalInterfaceEJB {
public String getName();
}
@Stateless
@Local(LocalInterfaceEJB.class)
public class LocalInterfaceEJBBean implements LocalInterfaceEJB {
public String getName() {
return new NameProvider().getName();
}
}
@RunWith(Arquillian.class)
public class IntegrationJarTestCase {
@Deployment
public static JavaArchive createDeployment() throws Exception {
return create(JavaArchive.class)
.addClasses(
LocalInterfaceEJB.class,
LocalInterfaceEJBBean.class);
}
@EJB
private LocalInterfaceEJB bean;
@Test
public void shouldBeAbleToInjectEJBAsInstanceVariable() throws Exception {
assertNotNull("Verify that the Bean has been injected", bean);
assertEquals("Arquillian", bean.getName());
}
}
/~redacted~/
I completely ignored Java code pasted here in comments, as I didn't recognize it as difference wrt presented reproducer but only as reference. Didn't read it 12hrs ago. Didn't read it 1hr ago.
But now that I did, I think I know.
This final link:
- https://github.com/pzygielo/omnifishee-arquillian-container-glassfish/pull/5, OR
- https://github.com/pzygielo/omnifishee-arquillian-container-glassfish/pull/6
in chain of changes https://github.com/pzygielo/omnifishee-arquillian-container-glassfish/pulls?q=is%3Aopen+is%3Apr+label%3Aglassfish-25535 seems to work for me.
I'm not sure what is the nature of IntegrationJarTestCase w/o that and which mechanism injects into it when it's not yet EJB, but with @Stateless all is fine. Or @Injecting bean by interface instead of @EJBing it is also fine.
Empty beans.xml makes it implicit bean archive of CDI, doesn't it?
Eventually I will also check if that behaviour really changed since 6.2.5.
On 6.2.5 the test succeeded
What does it mean? Please share commit hash.
On my side, standalone GF 6.2.5/7.0.25/8.0.0-M12 - all seem to handle such case correctly and the same (not needing @Inject or @Stateless, just like in b115b4f).
But not the test under Arquillian with GlassFish-embedded 7.0.25.
-
git clone https://github.com/pzygielo/omnifishee-arquillian-container-glassfish -b standalone7 -
cd omnifishee-arquillian-container-glassfish -
mvn -f glassfish-embedded -Dtest=IntegrationJarTestCaseclean clean testand intercept WAR prepared by arquillian as/tmp/gf25535.war. - the arquillian test fails, maven finishes
- start GF 7.0.25/8.0.0-M12 domain (might be with
--verbose) - autodeploy intercepted
gf25535.war - trigger the test:
$ curl "http://localhost:8080/gf25535/ArquillianServletRunnerEE9?className=org.omnifaces.arquillian.container.glassfish.embedded.app.IntegrationJarTestCase&methodName=shouldBeAbleToInjectEJBAsInstanceVariable"
The result contains nothing (https://github.com/arquillian/arquillian-jakarta/blob/d4f7b2ade43058a669a6be7ccdeb022ef80dc7ba/protocols/servlet-jakarta/src/main/java/org/jboss/arquillian/protocol/servlet5/runner/ServletTestRunner.java#L143-L164), but there is server.log/console entry:
[#|2025-06-11T19:20:33.723177+02:00|INFO|GF 7.0.25|jakarta.enterprise.logging.stdout|_ThreadID=48;_ThreadName=http-listener-1(3);_LevelValue=800;|
GF25535 Name: Arquillian|#]
and
[#|2025-06-11T19:38:09.064139+02:00|INFO|GF 8.0.0-M12|jakarta.enterprise.logging.stdout|_ThreadID=40;_ThreadName=http-listener-1(3);_LevelValue=800;|
GF25535 Name: Arquillian|#]
to show bean is operational.
IMO at least distributions are fine, and if there is problem in GF, it's in embedded.
IMO everything is fine with JNDI names, hence the title could be modified.
@pzygielo , can you just try this?
git remote add dmatej [email protected]:dmatej/arquillian-container-glassfish.git
git fetch dmatej
git checkout -b dmatej-jndi-name dmatej/jndi-name
mvn clean install -Dversion.glassfish=7.0.25
And it ends this way:
[ERROR] Failures:
[ERROR] IntegrationJarTestCase.shouldBeAbleToInjectEJBAsInstanceVariable:93 Verify that the Bean has been injected
[INFO]
[ERROR] Tests run: 15, Failures: 1, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary for Arquillian Container Parent GlassFish 2.0.0-SNAPSHOT:
[INFO]
[INFO] Arquillian Container Parent GlassFish .............. SUCCESS [ 0.175 s]
[INFO] Arquillian Container GlassFish Common Services ..... SUCCESS [ 2.668 s]
[INFO] Arquillian Container GlassFish Managed ............. SUCCESS [ 11.626 s]
[INFO] Arquillian Container GlassFish Remote .............. SUCCESS [ 0.149 s]
[INFO] Arquillian Container GlassFish Embedded ............ FAILURE [ 5.388 s]
[INFO] GlassFish client libs for Jakarta EE 9 ............. SKIPPED
[INFO] GlassFish client libs for Jakarta EE 10 ............ SKIPPED
[INFO] GlassFish client libs for Jakarta EE 11 ............ SKIPPED
[INFO] Environment Setup and Propagation .................. SKIPPED
[INFO] integration-tests .................................. SKIPPED
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 20.422 s
[INFO] Finished at: 2025-06-26T00:08:53+02:00
[INFO] ------------------------------------------------------------------------
can you just try this? ... And it ends this way:
[ERROR] Failures: [ERROR] IntegrationJarTestCase.shouldBeAbleToInjectEJBAsInstanceVariable:93 Verify that the Bean has been injected [INFO]
I do see the same locally, I do.
I still can't reproduce it with standalone GF.
~I have no final conclusion but here is what I've found so far:~
Q1: Who is injecting bean into IntegrationJarTestCase in run/test-time?**
~It's not GlassFish, but this Arquillian piece of code~ https://github.com/eclipse-ee4j/glassfish/blob/7ee8f53bb81d86334e72f510e3027a777eebb4d1/testenrichers/ejb/src/main/java/org/jboss/arquillian/testenricher/ejb/EJBInjectionEnricher.java#L247-L259
EDIT: It's rather CDI*Enricher.
~When tested with GF 6.2.5, the last jndiName = "org.omnifaces.arquillian.container.glassfish.embedded.app.LocalInterfaceEJB is being found in context and populated in TestCase.~
~Note the comment for that case:~ https://github.com/eclipse-ee4j/glassfish/blob/7ee8f53bb81d86334e72f510e3027a777eebb4d1/testenrichers/ejb/src/main/java/org/jboss/arquillian/testenricher/ejb/EJBInjectionEnricher.java#L242-L243
~With GF 7.0.25 Arquillian can't find it.~
With explicit @Stateless(name) the lookup finds: [5] = "java:module/LocalInterfaceEJB".
Q2: Who is populating Context that is used in Enricher?
https://github.com/eclipse-ee4j/glassfish/blob/7ee8f53bb81d86334e72f510e3027a777eebb4d1/testenrichers/ejb/src/main/java/org/jboss/arquillian/testenricher/ejb/EJBInjectionEnricher.java#L247
~This is for me learn next.~ EDIT: Need to learn different things than I thought yesterday.
But at this moment I see no fault in GlassFish, and the reason of change that Arquillian is unable to handle is still to be discovered.
I suggest to remove bug label and classification of this issue.
Let's consider my comment as invalid for now.