HOAB

History of a bug

EJB not found when deploying from Intellij IDEA to JBoss

Rédigé par gorki Aucun commentaire

Le problème :

I follow the integration guide from JetBrains :

But I deploy my application (that use EJB), EJB (referenced by @EJB and defined in ejb-jar.xml) were not found

Solution :

After a few tests, I found that JBoss require that a deployment directory must finished with a known extension

JBAS015010: Le scanner de déploiement a trouvé un répertoire nommé META-INF qui n'était pas à l'intérieur d'un répertoire dont le nom se termine par .ear, .jar, .rar, .sar ou .war.

So when I modify the output dir of the artifact deployed to jboss from "mywebapp" to "mywebapp.war", it works...

 

@EJB @Singleton et ConcurrencyManagement

Rédigé par gorki Aucun commentaire

Le problème :

Un EJB singleton qui sert de cache remonte une erreur avec JBoss 7.1.1 :

EJB Invocation failed on component XXXX for method public java.lang.Object:
javax.ejb.EJBTransactionRolledbackException: JBAS014373: EJB 3.1 PFD2 4.8.5.5.1
concurrent access timeout on org.jboss.invocation.InterceptorContext$Invocation@398e7b17 
- could not obtain lock within 5000MILLISECONDS

Solution :

Tout est déjà écrit bien sur, encore aurait-il fallu le lire :)
Par défaut les EJB @Singleton sont

  1. @ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)

  2. protégés par un @Lock(LockType.WRITE)

donc les méthodes sont synchronisés par le container. On peut

  • soit passer la méthode ou la classe en LockType.READ,
  • soit passer en Bean-managed (@ConcurrencyManagement(ConcurrencyManagementType.BEAN)). Là c'est vous qui gérer le tout.

Pour reproduire systématiquement, il suffit de mettre un sleep de 6s dans la méthode problématique.

Note:

  • Si le pool des ejb n'est pas assez grand on a un permit timeout et non un concurrent ascess timeout.
  • Le timeout sous JBoss est configuré dans cette section très intéressante :
<subsystem xmlns="urn:jboss:domain:ejb3:1.2">
            <session-bean>
                <stateless>
                    <bean-instance-pool-ref pool-name="slsb-strict-max-pool"/>
                </stateless>
                <stateful default-access-timeout="5000" cache-ref="simple"/>
                <singleton default-access-timeout="5000"/>
            </session-bean>
            <pools>
                <bean-instance-pools>
                    <strict-max-pool name="slsb-strict-max-pool" max-pool-size="20" instance-acquisition-timeout="5" instance-acquisition-timeout-unit="MINUTES"/>
                    <strict-max-pool name="mdb-strict-max-pool" max-pool-size="20" instance-acquisition-timeout="5" instance-acquisition-timeout-unit="MINUTES"/>
                </bean-instance-pools>
            </pools>
            <caches>
                <cache name="simple" aliases="NoPassivationCache"/>
                <cache name="passivating" passivation-store-ref="file" aliases="SimpleStatefulCache"/>
            </caches>
            <passivation-stores>
                <file-passivation-store name="file"/>
            </passivation-stores>
            <async thread-pool-name="default"/>
            <timer-service thread-pool-name="default">
                <data-store path="timer-service-data" relative-to="jboss.server.data.dir"/>
            </timer-service>
            <remote connector-ref="remoting-connector" thread-pool-name="default"/>
            <thread-pools>
                <thread-pool name="default">
                    <max-threads count="10"/>
                    <keepalive-time time="100" unit="milliseconds"/>
                </thread-pool>
            </thread-pools>
        </subsystem>

 

 

@EJB / @Inject ne fonctionne pas

Rédigé par gorki Aucun commentaire

Le problème :

Un EJB est appelé, mais ne vois pas ses attributs remplis par le container : les attributs normalement remplis par @Inject et @EJB ont une valeur null.

Malgré les vérifications habituelles, je n'avais toujours pas d'attributs injectés et du coup des NullPointerException à la pelle.

Solution :

Vérifier les éléments suivants à vérifier sur la classe appelée :

  1. présence du @Stateless/@Singleton/@Stateful sur la classe
  2. classe non finale
  3. classe appelante instanciée par le container
    • Soit via @Inject / @EJB elle-même
    • Soit suivant la méthode du container :
      1. pour l'auto-injection OpenEJB/TomEE,
      2. soit suite à un @Startup, une servlet, @Path, etc...
  4. si vous êtes en EJB 3.0, présence du META-INF/beans.xml
  5. méthode appelée publique non finale

C'était ce dernier cas qui m'a donné du fil à retordre. Tout était bon et pourtant lors de l'appel d'une méthode particulière, l'objet pourtant instancié par le container ne voyais pas ses attributs injectés. Le fait d'avoir une méthode finale empêche le container d'injecter ses outils autour de la méthode.

Fil RSS des articles de ce mot clé