Bug 1366526
| Summary: | [GSS](6.4.z) EJB method invocation hangs when a bean is configured with both @Startup annotation and <init-on-startup> in ejb-jar.xml | ||||||||
|---|---|---|---|---|---|---|---|---|---|
| Product: | [JBoss] JBoss Enterprise Application Platform 6 | Reporter: | Masafumi Miura <mmiura> | ||||||
| Component: | EJB | Assignee: | Fedor Gavrilov <fgavrilo> | ||||||
| Status: | CLOSED CURRENTRELEASE | QA Contact: | Jan Martiska <jmartisk> | ||||||
| Severity: | unspecified | Docs Contact: | |||||||
| Priority: | unspecified | ||||||||
| Version: | 6.4.9 | CC: | bmaxwell, david.lloyd, fgavrilo, jbilek, jtruhlar, msochure | ||||||
| Target Milestone: | CR1 | ||||||||
| Target Release: | EAP 6.4.11 | ||||||||
| Hardware: | Unspecified | ||||||||
| OS: | Unspecified | ||||||||
| Whiteboard: | |||||||||
| Fixed In Version: | Doc Type: | If docs needed, set a value | |||||||
| Doc Text: | Story Points: | --- | |||||||
| Clone Of: | Environment: | ||||||||
| Last Closed: | 2017-01-17 13:10:41 UTC | Type: | Bug | ||||||
| Regression: | --- | Mount Type: | --- | ||||||
| Documentation: | --- | CRM: | |||||||
| Verified Versions: | Category: | --- | |||||||
| oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |||||||
| Cloudforms Team: | --- | Target Upstream Version: | |||||||
| Embargoed: | |||||||||
| Bug Depends On: | 1310908 | ||||||||
| Bug Blocks: | 1319040, 1361648, 1379471 | ||||||||
| Attachments: |
|
||||||||
|
Description
Masafumi Miura
2016-08-12 08:49:23 UTC
When both @Startup annotation and <init-on-startup>true</init-on-startup> in ejb-jar.xml are configured for bean, "description.getModuleDescription().registerStartupBean()" is called twice in StartupMergingProcessor#handleAnnotations() and in StartupMergingProcessor#handleDeploymentDescriptor().
This makes the startup countdown (startupBeansCount in EEModuleDescription) have a wrong value (actual bean count + 1). This causes the count down never reaches 0 and EJB invocation awaits forever.
---------------------------------------------------------
* ejb3/src/main/java/org/jboss/as/ejb3/deployment/processors/merging/AbstractMergingProcessor.java
~~~
81 private void processComponentConfig(final DeploymentUnit deploymentUnit, final EEApplicationClasses applicationClasses, final Module module, final DeploymentReflectionIndex deploymentReflectionIndex, final T description) throws DeploymentUnitProcessingException {
82
83 final Class<?> componentClass;
84 try {
85 componentClass = module.getClassLoader().loadClass(description.getEJBClassName());
86 } catch (ClassNotFoundException e) {
87 throw MESSAGES.failToLoadEjbClass(description.getEJBClassName(),e);
88 }
89
90 if (!MetadataCompleteMarker.isMetadataComplete(deploymentUnit)) {
91 handleAnnotations(deploymentUnit, applicationClasses, deploymentReflectionIndex, componentClass, description);
92 }
93 handleDeploymentDescriptor(deploymentUnit, deploymentReflectionIndex, componentClass, description);
94 }
~~~
* ejb3/src/main/java/org/jboss/as/ejb3/deployment/processors/merging/StartupMergingProcessor.java
~~~
46 @Override
47 protected void handleAnnotations(final DeploymentUnit deploymentUnit, final EEApplicationClasses applicationClasses, final DeploymentReflectionIndex deploymentReflectionIndex, final Class<?> componentClass, final SingletonComponentDescription description) throws DeploymentU nitProcessingException {
48 EEModuleClassDescription clazz = applicationClasses.getClassByName(componentClass.getName());
49 if (clazz != null) {
50 final ClassAnnotationInformation<Startup, Object> data = clazz.getAnnotationInformation(Startup.class);
51 if (data != null) {
52 if (!data.getClassLevelAnnotations().isEmpty()) {
53 description.initOnStartup();
54 description.getModuleDescription().registerStartupBean();
55 }
56 }
57 }
58 }
59
60 @Override
61 protected void handleDeploymentDescriptor(final DeploymentUnit deploymentUnit, final DeploymentReflectionIndex deploymentReflectionIndex, final Class<?> componentClass, final SingletonComponentDescription description) throws DeploymentUnitProcessingException {
62 SessionBeanMetaData data = description.getDescriptorData();
63 if (data instanceof SessionBean31MetaData) {
64 SessionBean31MetaData singletonBeanMetaData = (SessionBean31MetaData) data;
65 Boolean initOnStartup = singletonBeanMetaData.isInitOnStartup();
66 if (initOnStartup != null && initOnStartup) {
67 description.initOnStartup();
68 description.getModuleDescription().registerStartupBean();
69 }
70 }
71 }
~~~
* ee/src/main/java/org/jboss/as/ee/component/EEModuleDescription.java
~~~
308 public int getStartupBeansCount() {
309 return this.startupBeansCount;
310 }
311
312 public int registerStartupBean() {
313 return ++this.startupBeansCount;
314 }
~~~
I think StartupMergingProcessor#handleDeploymentDescriptor() should skip a processing if it's already marked as InitOnStartup by StartupMergingProcessor#handleAnnotations().
So, I suggest that StartupMergingProcessor#handleDeploymentDescriptor() should check SingletonComponentDescription#isInitOnStartup() before continuing the processing.
As far as I did a simple test (running the attached reproducer), the following patch can fix the issue:
~~~
diff --git a/ejb3/src/main/java/org/jboss/as/ejb3/deployment/processors/merging/StartupMergingProcessor.java b/ejb3/src/main/java/org/jboss/as/ejb3/deployment/processors/merging/StartupMergingProcessor.java
index 5e1937f..7fc0d84 100644
--- a/ejb3/src/main/java/org/jboss/as/ejb3/deployment/processors/merging/StartupMergingProcessor.java
+++ b/ejb3/src/main/java/org/jboss/as/ejb3/deployment/processors/merging/StartupMergingProcessor.java
@@ -59,13 +59,17 @@ public class StartupMergingProcessor extends AbstractMergingProcessor<SingletonC
@Override
protected void handleDeploymentDescriptor(final DeploymentUnit deploymentUnit, final DeploymentReflectionIndex deploymentReflectionIndex, final Class<?> componentClass, final SingletonComponentDescription description) throws DeploymentUnitProcessingException {
- SessionBeanMetaData data = description.getDescriptorData();
- if (data instanceof SessionBean31MetaData) {
- SessionBean31MetaData singletonBeanMetaData = (SessionBean31MetaData) data;
- Boolean initOnStartup = singletonBeanMetaData.isInitOnStartup();
- if (initOnStartup != null && initOnStartup) {
- description.initOnStartup();
- description.getModuleDescription().registerStartupBean();
+ if (description.isInitOnStartup()) {
+ // Skip. This is already marked as InitOnStartup by @Startup annotation.
+ } else {
+ SessionBeanMetaData data = description.getDescriptorData();
+ if (data instanceof SessionBean31MetaData) {
+ SessionBean31MetaData singletonBeanMetaData = (SessionBean31MetaData) data;
+ Boolean initOnStartup = singletonBeanMetaData.isInitOnStartup();
+ if (initOnStartup != null && initOnStartup) {
+ description.initOnStartup();
+ description.getModuleDescription().registerStartupBean();
+ }
}
}
}
~~~
Created attachment 1190307 [details] BZ1366526-potential-patch.diff Sorry to forget to mention information about a workaround. ### Workaround - Don't use both @Startup annotation and <init-on-startup> in ejb-jar.xml to configure a singleton Startup beans - Specify either @Startup annotation or <init-on-startup>. (In reply to Masafumi Miura from comment #4) > Sorry to forget to mention information about a workaround. > > ### Workaround > > - Don't use both @Startup annotation and <init-on-startup> in ejb-jar.xml > to configure a singleton Startup beans > - Specify either @Startup annotation or <init-on-startup>. Thank you! This should be fine. EAP6 PR: https://github.com/jbossas/jboss-eap/pull/2830 Verified with EAP 6.4.11.CP.CR1 Retroactively bulk-closing issues from released EAP 6.4 cummulative patches. |