EJB3

From no name for this wiki
Jump to: navigation, search

EJB3 Examples für Glassfish 2.x. Für Classpathsettings der Clients siehe Glassfish.

Stateless Session Bean

Bemerkungen:

  • Standalone Clients können die @EJB Annotation nicht verwenden.
  • Der Defaultname fürs Remote Interface im JNDI ist full qualified class name of remote interface. In dem Fall also learningejb.SimpleSessionBeanRemote.
  • Siehe http://wiki.netbeans.org/CreatingEJB3UsingNetbeansAndGlassfish
  • Der Port für ORB kann in der Adminkonsole nachgeschaut werden. IIOP Zielgeräte.

Bean

package learningejb;

import javax.ejb.Stateless;

@Stateless
public class SimpleSessionBeanBean implements SimpleSessionBeanRemote, SimpleSessionBeanLocal {

    public void helloWorld(final String inputtext) {
        System.out.printf("Hello World");
    }
    
}

Remote

package learningejb;

import javax.ejb.Remote;

@Remote
public interface SimpleSessionBeanRemote {

    void helloWorld(final String inputtext);
    
}

Local

package learningejb;

import javax.ejb.Local;

@Local
public interface SimpleSessionBeanLocal {
    
}

Client

package learningejb3;

import java.util.Properties;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import learningejb.SimpleSessionBeanRemote;

public class Main {

  
    public static void main(String[] args) {
        System.out.println("Starting application");
        try {
            Properties props = new Properties();
            props.setProperty("java.naming.factory.initial", "com.sun.enterprise.naming.SerialInitContextFactory");
            props.setProperty("java.naming.factory.url.pkgs", "com.sun.enterprise.naming");
            props.setProperty("java.naming.factory.state", "com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");
            props.setProperty("org.omg.CORBA.ORBInitialHost", "localhost");
            props.setProperty("org.omg.CORBA.ORBInitialPort", "3712");

            InitialContext ctx = new InitialContext(props);
            SimpleSessionBeanRemote testEJB = (SimpleSessionBeanRemote) ctx.lookup("learningejb.SimpleSessionBeanRemote");
            testEJB.helloWorld("hello");
            
        } catch (NamingException nex) {
            nex.printStackTrace();
        }
    }
}

Message Driven Bean

message driven bean

package learningejb;

import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

@MessageDriven(mappedName = "mydestination", activationConfig =  {
        @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
        @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")
    })
public class MyMessageConsumerBean implements MessageListener {
    
    public MyMessageConsumerBean() {
    }

    public void onMessage(Message message) {
        System.out.println("Hello from message");
        if(message instanceof TextMessage){
            TextMessage tm = (TextMessage) message;
            try {
                System.out.println(tm.getText());
            } catch (JMSException ex) {
                ex.printStackTrace();
            }
        }
    }    
}

standalone client, message producer

Folgende Klasse verschickt eine Message an eine Queue. Es ist eine standalone Applikation, resource injection ist daher nicht möglich:

package scbcdjmsclient;

import java.util.Properties;
import javax.jms.Connection;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.QueueConnectionFactory;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class Main {

    public static void main(String[] args) {
        System.out.println("Starting application");
        try {
            Properties props = new Properties();
            props.setProperty("java.naming.factory.initial", "com.sun.enterprise.naming.SerialInitContextFactory");
            props.setProperty("java.naming.factory.url.pkgs", "com.sun.enterprise.naming");
            props.setProperty("java.naming.factory.state", "com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");
            props.setProperty("org.omg.CORBA.ORBInitialHost", "localhost");
            props.setProperty("org.omg.CORBA.ORBInitialPort", "3712");

            InitialContext ctx = new InitialContext(props);
            QueueConnectionFactory connectionFactory = (QueueConnectionFactory) ctx.lookup("myconnectionfactory");
            Queue  queue =  (Queue) ctx.lookup("mydestination");
            Connection connection  = connectionFactory.createConnection();
            Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
            MessageProducer procucer = session.createProducer(queue);
            TextMessage message = session.createTextMessage("a text message hello world");
            procucer.send(message);
        }
        catch(JMSException jmsex){
            jmsex.printStackTrace();
        }
        catch (NamingException nex) {
            nex.printStackTrace();
        }
    }
}

ejb3 message procucer

Anbei ein EJB3, welches Messages verschickt.

package learningejb;

import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.jms.Connection;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.QueueConnectionFactory;
import javax.jms.Session;
import javax.jms.TextMessage;

@Stateless
public class SimpleSessionBeanBean implements SimpleSessionBeanRemote {

    @Resource(mappedName = "mydestination")
    Queue queue;
    
    @Resource(mappedName = "myconnectionfactory")
    QueueConnectionFactory connectionFactory;

    public void helloWorld(String inputtext) {
        try {
            Connection connection = connectionFactory.createConnection();
            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            MessageProducer procucer = session.createProducer(queue);
            TextMessage message = session.createTextMessage("a text message hello world");
            procucer.send(message);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Annotationless example

bean

package learningejb;

import javax.jms.Message;
import javax.jms.MessageListener;


public class MessageDriven2 implements MessageListener {

    public void onMessage(Message message) {
        System.out.println("message received !!!!!");
    }

}

ejb-jar.xml

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns = "http://java.sun.com/xml/ns/javaee" 
         version = "3.0" 
         xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd">
         <enterprise-beans>


             <message-driven>
                 <ejb-name>mymessagedrivenbean2</ejb-name>
                 <mapped-name>mydestination</mapped-name>
                 <ejb-class>learningejb.MessageDriven2</ejb-class>
                 <!-- message-destination-link>mydestname</message-destination-link -->
                 <message-destination-type>javax.jms.Queue</message-destination-type>
                 <activation-config>
                     <activation-config-property>
                         <activation-config-property-name>acknowledgeMode</activation-config-property-name>
                         <activation-config-property-value>Auto-acknowledge</activation-config-property-value>
                     </activation-config-property>
                 </activation-config>                 
             </message-driven>
             
         </enterprise-beans>

         <assembly-descriptor>

             <!-- nicht benutzt bei diesem Beispiel, nur zum Zeigen 
             <message-destination>
                 <message-destination-name>mydestname</message-destination-name>
                 <mapped-name>mydestination</mapped-name>                
             </message-destination>
             -->
         </assembly-descriptor>
</ejb-jar>

activation-config-properties

In diesem Abschnitt werden die Activation-Config-Properties beschrieben.

messageSelector

Mit dem Selector können Messages ausgewählt werden, welche von diesem Bean verarbeitet werden. Beispiel:

JMSType = 'car' AND color = 'blue' AND weight > 2500

destinationType

Mögiche Werte sind javax.jms.Topic und javax.jms.Queue.

subscriptionDurability

Mögliche Werte sind Durable und NonDurable


acknowledgeMode

Mögliche Werte sind AUTO_ACKNOWLEDGE und DUPS_OK_ACKNOWLEDGE.

Timer Services

remote

package learningejb;

import javax.ejb.Remote;

@Remote
public interface TimerExampleRemote {
    public void startTimer();
}

beanclass

Dieses Beispiel kreiert einen Intervall-Timer.

package learningejb;
import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerService;


@Stateless
public class TimerExampleBean implements TimerExampleRemote {

    @Resource
    TimerService timerService;

    @Timeout
    public void timeOut(Timer timer)
    {
        System.out.println("Hello from timer");
    }

    //remote method impl
    public void startTimer(){
        this.timerService.createTimer(2000, 3000, "some info");
    }
}

Security

Standalone EJB3 Client mit Authentication

Main Klasse mit Login:

package learningejb3;

import com.sun.appserv.security.ProgrammaticLogin;
import java.util.Properties;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import learningejb.SecuredRemote;


public class Main {

  
    public static void main(String[] args) {
        System.out.println("Starting application");
        try {
            Properties props = new Properties();
            props.setProperty("java.naming.factory.initial", "com.sun.enterprise.naming.SerialInitContextFactory");
            props.setProperty("java.naming.factory.url.pkgs", "com.sun.enterprise.naming");
            props.setProperty("java.naming.factory.state", "com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");
            props.setProperty("org.omg.CORBA.ORBInitialHost", "localhost");
            props.setProperty("org.omg.CORBA.ORBInitialPort", "3712");

            ProgrammaticLogin programmaticLogin = new ProgrammaticLogin();
            if(programmaticLogin.login("claude","claude") == false){
                System.out.println("login failed");
            }
            
            InitialContext ctx = new InitialContext(props);
            SecuredRemote testEJB = (SecuredRemote) ctx.lookup("learningejb.SecuredRemote");
            testEJB.sayHello();
            
        } catch (NamingException nex) {
            nex.printStackTrace();
        }
    }
}

appclientlogin.conf:

default {
  com.sun.enterprise.security.auth.login.ClientPasswordLoginModule required debug=true;
};

certificate {
  com.sun.enterprise.security.auth.login.ClientCertificateLoginModule required debug=true;
};

Startupargumente:

-Djava.security.auth.login.config=appclientlogin.conf

secured bean mit annotationen

package learningejb;

import javax.annotation.Resource;
import javax.annotation.security.DeclareRoles;
import javax.annotation.security.RolesAllowed;
import javax.ejb.EJBContext;
import javax.ejb.Stateless;

@Stateless
@DeclareRoles("role1")
@RolesAllowed("role1")
public class SecuredBean implements SecuredRemote {

    @Resource
    EJBContext context;

    public void sayHello() {
        System.out.println("Say hello from secured bean!");
        System.out.println("principal:" + context.getCallerPrincipal().getName());
    }
     
}

Zuordnung von Rollennamen im Code zu Security-Roles

package learningejb;

import javax.annotation.Resource;
import javax.annotation.security.DeclareRoles;
import javax.annotation.security.RolesAllowed;
import javax.ejb.EJB;
import javax.ejb.EJBContext;
import javax.ejb.Stateless;

@Stateless(name="SecuredBeanName", mappedName="SecuredBeanNameJNDI")
@DeclareRoles({"role1"})
public class SecuredBean implements SecuredRemote {

    @Resource
    EJBContext context;

    @EJB
    InnerLocal innerlocal;

    @RolesAllowed("role1")
    public void sayHello() {
        System.out.println("role1: " + context.isCallerInRole("role1")); //true if caller is assigned role1
        System.out.println("localrole: " + context.isCallerInRole("localrole")); //true if caller is assigned role1
    }
     
}
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns = "http://java.sun.com/xml/ns/javaee" 
         version = "3.0" 
         xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd">
         <enterprise-beans>
             <session>
                 <ejb-name>SecuredBeanName</ejb-name>
                 <security-role-ref>
                     <role-name>localrole</role-name>
                     <role-link>role1</role-link>
                 </security-role-ref>
             </session>
         </enterprise-beans>

         <assembly-descriptor>
             <security-role>
                 <role-name>role1</role-name>
             </security-role>
         </assembly-descriptor>
</ejb-jar>

Annotationless

Beispiel ohne Annotationen.

Bean

package learningejb;

import javax.interceptor.InvocationContext;


public class DescriptorBean implements DescriptionBeanRemote {

    public void sayHello(String astring){
        System.out.println("Say hello:" + astring);
    }
    
    public Object myaroundInvoke(InvocationContext invocationContext) throws Exception {
        System.out.println("In aroundInvoke");
	return invocationContext.proceed();
    }
}

Remote

package learningejb;

public interface DescriptionBeanRemote {

    public void sayHello(String astring);

}

ejb-jar.xml

<?xml version="1.0" encoding="UTF-8"?>

<ejb-jar xmlns = "http://java.sun.com/xml/ns/javaee" 
         version = "3.0" 
         xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd">
         <enterprise-beans>
             <session>
                 <description>a sample</description>
                 <display-name>a displayed name</display-name>
                 <ejb-name>ASimpleSessionBean</ejb-name>
                 <business-remote>learningejb.DescriptionBeanRemote</business-remote>
                 <ejb-class>learningejb.DescriptorBean</ejb-class>
                 <session-type>Stateless</session-type>
                 <transaction-type>Container</transaction-type>
                 <around-invoke>
                     <method-name>myaroundInvoke</method-name>
                 </around-invoke>
             </session>
         </enterprise-beans>

         <assembly-descriptor>
             <container-transaction>
                 <description>Transaction for requires new</description>
                 <method>
                     <ejb-name>ASimpleSessionBean</ejb-name>
                     <method-intf>Remote</method-intf>
                     <method-name>sayHello</method-name>
                     <method-params>
                         <method-param>java.lang.String</method-param>
                     </method-params>
                 </method>
                 <trans-attribute>RequiresNew</trans-attribute>
             </container-transaction>
         </assembly-descriptor>
</ejb-jar>

Interceptors

Interceptor

package learningejb;

import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;

public class MyInterceptor {

    @AroundInvoke
    public Object myaroundInvoke(InvocationContext invocationContext) throws Exception {
        System.out.println("In aroundInvoke");
	return invocationContext.proceed();
    }
}

Bean

package learningejb;

import javax.ejb.Stateless;
import javax.interceptor.Interceptors;

@Stateless
@Interceptors(MyInterceptor.class)
public class SimpleSessionBeanBean implements SimpleSessionBeanRemote, SimpleSessionBeanLocal {

    public void helloWorld(final String inputtext) {
        System.out.printf("Hello World");
    }
    
}

Annotationless sample

Will man auf Annotationen verzichten, dann ejb-jar.xml verwenden. Beispiel erstellt einen default interceptor.

<?xml version="1.0" encoding="UTF-8"?>

<ejb-jar xmlns = "http://java.sun.com/xml/ns/javaee" 
         version = "3.0" 
         xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd">
         <enterprise-beans>
             <session>
                 <description>a sample</description>
                 <display-name>a displayed name</display-name>
                 <ejb-name>ASimpleSessionBean</ejb-name>
                 <business-remote>learningejb.DescriptionBeanRemote</business-remote>
                 <ejb-class>learningejb.DescriptorBean</ejb-class>
                 <session-type>Stateless</session-type>
                 <transaction-type>Container</transaction-type>
                 <around-invoke>
                     <method-name>myaroundInvoke</method-name>
                 </around-invoke>
             </session>
         </enterprise-beans>

         <interceptors>
            <interceptor>
                <interceptor-class>learningejb.DefaultInterceptor</interceptor-class>
                <around-invoke>
                    <method-name>myaroundInvoke</method-name>
                </around-invoke>
            </interceptor>
         </interceptors>

         <assembly-descriptor>

             <container-transaction>
                 <description>Transaction for requires new</description>
                 <method>
                     <ejb-name>ASimpleSessionBean</ejb-name>
                     <method-intf>Remote</method-intf>
                     <method-name>sayHello</method-name>
                     <method-params>
                         <method-param>java.lang.String</method-param>
                     </method-params>
                 </method>
                 <trans-attribute>RequiresNew</trans-attribute>
             </container-transaction>

            <interceptor-binding>
                 <ejb-name>*</ejb-name>
                 <interceptor-class>learningejb.DefaultInterceptor</interceptor-class>
             </interceptor-binding>
         </assembly-descriptor>

</ejb-jar>


simple environment entries

injection with annotations

bean

package learningejb;


import javax.annotation.Resource;
import javax.ejb.Stateless;

@Stateless
public class SimpleSessionBeanBean  implements SimpleSessionBeanRemote {

    @Resource
    private int myvalue1;

    public void helloWorld(String inputtext) {
        System.out.println("myvalue1:" + myvalue1);
    }
    
}

descirptor

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns = "http://java.sun.com/xml/ns/javaee" 
         version = "3.0" 
         xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd">
         <enterprise-beans>

             <session>
                 <ejb-name>SimpleSessionBeanBean</ejb-name>
                 <env-entry>
                     <env-entry-name>learningejb.SimpleSessionBeanBean/myvalue1</env-entry-name>
                     <env-entry-type>java.lang.Integer</env-entry-type>
                     <env-entry-value>888</env-entry-value>
                 </env-entry>
             </session>

         </enterprise-beans>
</ejb-jar>

injection with descriptor

bean

package learningejb;

import javax.ejb.Stateless;

@Stateless
public class SimpleSessionBeanBean  implements SimpleSessionBeanRemote {


    private int myvalue1;

    public void helloWorld(String inputtext) {
        System.out.println("myvalue1:" + myvalue1);
    }
    
}

descriptor

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns = "http://java.sun.com/xml/ns/javaee" 
         version = "3.0" 
         xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd">
         <enterprise-beans>

             <session>
                 <ejb-name>SimpleSessionBeanBean</ejb-name>
                 <env-entry>
                     <env-entry-name>learningejb.SimpleSessionBeanBean/myvalue1</env-entry-name>
                     <env-entry-type>java.lang.Integer</env-entry-type>
                     <env-entry-value>888</env-entry-value>
                     <injection-target>
                         <injection-target-class>learningejb.SimpleSessionBeanBean</injection-target-class>
                         <injection-target-name>myvalue1</injection-target-name>
                     </injection-target>
                 </env-entry>
             </session>
         </enterprise-beans>
</ejb-jar>

ejb ref

ejb-ref in descriptor

Bean

package learningejb;

import javax.annotation.security.RolesAllowed;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;

@Stateless
public class SimpleSessionBeanBean  implements SimpleSessionBeanRemote {


    private int myvalue1;

    private SecuredLocal reftoother;

    @RolesAllowed("role1")
    public void helloWorld(String inputtext) {
        System.out.println("myvalue1:" + myvalue1);
        reftoother.sayHello();
    }
    
}

descriptor

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns = "http://java.sun.com/xml/ns/javaee" 
         version = "3.0" 
         xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd">
         <enterprise-beans>

             <session>
                 <ejb-name>SimpleSessionBeanBean</ejb-name>
                 <env-entry>
                     <env-entry-name>learningejb.SimpleSessionBeanBean/myvalue1</env-entry-name>
                     <env-entry-type>java.lang.Integer</env-entry-type>
                     <env-entry-value>888</env-entry-value>
                     <injection-target>
                         <injection-target-class>learningejb.SimpleSessionBeanBean</injection-target-class>
                         <injection-target-name>myvalue1</injection-target-name>
                     </injection-target>
                 </env-entry>
                 <ejb-local-ref>
                     <ejb-ref-name>refbean</ejb-ref-name>
                     <ejb-ref-type>Session</ejb-ref-type>
                     <local>learningejb.SecuredLocal</local>
                     <ejb-link>SecuredBeanName</ejb-link>
                     <injection-target>
                         <injection-target-class>learningejb.SimpleSessionBeanBean</injection-target-class>
                         <injection-target-name>reftoother</injection-target-name>
                     </injection-target>

                 </ejb-local-ref>   
             </session>

             <session>
                 <ejb-name>SecuredBeanName</ejb-name>
                 <env-entry>
                     <env-entry-name>learningejb.SecuredBean/myvalue1</env-entry-name>
                     <env-entry-type>java.lang.Integer</env-entry-type>
                     <env-entry-value>888</env-entry-value>                     
                 </env-entry>
                 <security-role-ref>
                     <role-name>localrole</role-name>
                     <role-link>role1</role-link>
                 </security-role-ref>
             </session>
         </enterprise-beans>

         <assembly-descriptor>
             <security-role>
                 <role-name>role1</role-name>
             </security-role>
        </assembly-descriptor>
</ejb-jar>

exceptions

Applicationexception Example. JEE unterscheidet zwischen System und Application-Exceptions.

package learningejb;

import javax.ejb.ApplicationException;

@ApplicationException(rollback=true)
public class MyAppEx extends RuntimeException {

}

Webservice Endpoint, JAX-WS

Die WSDL URL kann in der Amdministratorkonsole von Glassfish nachgeschaut werden.

Beispiel 1, simple

package learningejb;

import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.xml.ws.WebServiceContext;


@WebService
@Stateless
public class SimpleSessionBeanBean {

    @Resource
    WebServiceContext webserviceContext;


    @WebMethod
    public void aWebMethod(final String hello)
    {
        System.out.println("Hello from webmethod");
    }
    
}

Transactions

Transactionattributes

Requires

If the client is running within a transaction and invokes the enterprise bean’s method, the method executes within the client’s transaction. If the client is not associated with a transaction, the container starts a new transaction before running the method. The Required attribute is the implicit transaction attribute for all enterprise bean methods running with container-managed transaction demarcation. You typically do not set the Required attribute unless you need to override another transaction attribute. Because transaction attributes are declarative, you can easily change them later.

RequiresNew

If the client is running within a transaction and invokes the enterprise bean’s method, the container takes the following steps: 1. Suspends the client’s transaction 2. Starts a new transaction 3. Delegates the call to the method 4. Resumes the client’s transaction after the method completes

Mandatory

If the client is running within a transaction and invokes the enterprise bean’s method, the method executes within the client’s transaction. If the client is not associated with a transaction, the container throws the TransactionRequiredException.

Not supported

If the client is running within a transaction and invokes the enterprise bean’s method, the container suspends the client’s transaction before invoking the method. After the method has completed, the container resumes the client’s transaction. If the client is not associated with a transaction, the container does not start a new transaction before running the method. Use the NotSupported attribute for methods that don’t need transactions. Because transactions involve overhead, this attribute may improve performance.

Supports

If the client is running within a transaction and invokes the enterprise bean’s method, the method executes within the client’s transaction. If the client is not associated with a transaction, the container does not start a new transaction before running the method. Because the transactional behavior of the method may vary, you should use the Supports attribute with caution.

Never

If the client is running within a transaction and invokes the enterprise bean’s method, the container throws a RemoteException. If the client is not associated with a transaction, the container does not start a new transaction before running the method.

Resources