Wednesday Mar 23, 2011

EJB.next

Dear EJB users,

As you may already know, Ken Saks left Oracle several months ago.

In addition to the great work that he accomplished while leading EJB 3.1, Ken's posts on this blog have been a very useful source of information to the community.

While Ken will no longer be blogging here, we plan to keep this blog around as a valuable resource on EJB.

Meanwhile, EJB is moving forward. We plan to submit a JSR for EJB 3.2 to the JCP shortly. Marina Vatkina and I will be leading this JSR, and we will be keeping you posted as work on it progresses. You'll be able to follow us on:

http://blogs.sun.com/ldemichiel/
http://blogs.sun.com/marina/

Thanks for your support!

Linda DeMichiel

Tuesday Mar 23, 2010

Application-specified Portable JNDI Names

The EJB 3.1 specification defines portable global, application-scoped, and module-scoped JNDI names for all session bean components. This ensures a standard syntax by which session beans can be identified. Standard names are registered automatically during deployment, and are derived from application metadata such as module name, component name, etc.

While this solves the JNDI name portability issue, it doesn't address the case where developers prefer to choose JNDI names themselves. This application-specified approach can also be solved portably using some new Java EE 6 naming functionality for environment dependencies.

Here's a simple stateless session bean exposing a Remote business interface :

   1:  @Stateless
   2:  public class FooBean implements FooRemote { ... }

Assuming this component is deployed in a stand-alone ejb-jar module called foo.jar, its resulting portable JNDI names would be :

java:global/foo/FooBean

java:app/foo/FooBean

java:module/FooBean

The developer can select an additional JNDI name that resolves to a particular client view of a session bean by using the @EJB annotation. Starting with Java EE 6, the @EJB name() attribute value can be prefixed with any one of the three portable Java EE namespaces : java:global, java:app, java:module. This has the effect of exporting the dependency into the selected scope.

Using our example, to expose the Remote interface of FooBean within the global namespace under "examples/foo/remote", the following @EJB dependency could be added to the class-level of FooBean.java.

   1:  @EJB(name="java:global/examples/foo/remote",
   2:       beanInterface=FooRemote.class)

After deployment, any code with access to the application server's naming service can acquire an EJB reference to FooBean's remote interface as follows :

   1:  InitialContext ic = new InitialContext();
   2:  FooRemote fooRef  = (FooRemote) 
   3:      ic.lookup("java:global/examples/foo/remote");

Note that the fact that the developer chooses to expose a session bean under an additional JNDI name does not impact the registration of the default portable JNDI names in any way. It merely means there is one more string that resolves to the same target session bean.

A few other things to highlight :

  • The @EJB annotation does not have to be declared on the bean whose interface is being exposed. It can appear anywhere @EJB annotations are allowed.
  • The same EJB dependency could be declared as an ejb-ref within a standard deployment descriptor like ejb-jar.xml instead of as an @EJB annotation.
  • The additional name() attribute functionality can also be used with other Java EE environment annotations such as @Resource.

Friday Dec 11, 2009

Application Startup / Shutdown Callbacks

Developers often need to execute code at the point that an application is initializing or shutting down. The Servlet spec has supported this case for many years via ServletContextListener notifications. However, the EJB Specification has never offered equivalent functionality. The addition of Singleton EJB 3.1 components allows us to fill that gap by leveraging the Singleton life cycle to receive application startup and shutdown callbacks.

Here's a simple example :

   1:  @Startup
   2:  @Singleton
   3:  public class FooBean {
   4:   
   5:    @PostConstruct 
   6:    void atStartup() { ... }
   7:   
   8:    @PreDestroy
   9:    void atShutdown() { ... }
  10:   
  11:  }

The @Startup annotation forces Singleton initialization to occur eagerly during the application startup sequence. After any injection has taken place, the container calls the bean's @PostConstruct method. Singleton @PostConstruct methods have access to the full set of container services : other EJB components, JPA EntityManagers, the TimerService, etc. This allows a rich set of business logic to be performed during initialization. In addition, unlike other EJB component types, any container-managed transaction behavior for the bean applies to a Singleton's @PostConstruct method.

Independent of whether a Singleton is initialized eagerly or lazily, the bean instance can request a shutdown notification by defining a @PreDestroy method. Since the Singleton bean instance life cycle is tied to the container's life cycle, this method will be called when the application is shutting down.

Singletons

One of the long-standing limitations of the EJB component model has been the inability to easily share application-scoped state. The EJB 3.1 Singleton component solves this problem.

A Singleton is a new kind of Session bean that is guaranteed to be instantiated once per application (per server instance). A Singleton bean instance lives for the duration of its associated container. Singletons have much in common with Stateful and Stateless Session beans :

  • Support for Container Managed Transactions (CMT) and Bean Managed Transactions (BMT)
  • Ability to expose multiple independent client views ( No-interface, Local, Remote, Web Service )
  • EJB reference based client programming model
  • Access to container services for injection, resource manager access , timers, etc.

Here's a simple Singleton that provides some read-only configuration data :


   1:  @Singleton
   2:  public class SharedConfig {
   3:            
   4:    private ConfigData config;
   5:    
   6:    @PostConstruct 
   7:    private void init() {
   8:      // initialize configuration data
   9:      config = ...;
  10:    }
  11:       
  12:    public int getPropertyA() {
  13:      return config.propertyA;
  14:    }
  15:  }

It's common for such shared state to be very large and have significant setup costs. Storing it within a singleton guarantees efficient use of memory and avoids the overhead of redundant initialization.

Client access is easy -- just acquire a Singleton EJB reference through injection or lookup :


   1:  @Stateless
   2:  public class FooBean {
   3:   
   4:    @EJB
   5:    private SharedConfig configBean;
   6:   
   7:    public void foo() {
   8:      int propertyA = configBean.getPropertyA();
   9:      ...
  10:    }
  11:  }

Reusing the standard session bean client view for Singletons has the added benefit of allowing access from many kinds of clients, not just other EJB components. This makes it easy to share state between the web components and EJB components in an application.

Concurrency is another important Singleton topic. Singletons are intended to be called by many clients at once. However, the EJB component model has always guaranteed that no more than one thread has access to a particular bean instance at a time. Offering only that threading policy for Singletons would ensure correctness but would be too restrictive from a performance standpoint.

In order to balance these concerns, the container ensures single-threaded access to Singletons by default, but the developer can choose between two additional concurrency policies : container-managed concurrency (CMC) and bean-managed concurrency (BMC).

With CMC, developers use method-level shared/exclusive locks to tell the container when it's OK for multiple callers to have concurrent access to the bean instance. An invocation that can not proceed due to locks is blocked until it can make forward progress or until an optionally-specified timeout is reached. In CMC mode, the container is still in control but the fact that instance-level concurrency can occur boosts performance. The developer is freed from using Java SE level synchronization primitives to protect instance state.

Here's a slightly modified version of the previous Singleton example, this time using CMC :


   1:  @Singleton
   2:  public class SharedConfig {
   3:            
   4:    private ConfigData config; 
   5:       
   6:    @Lock(LockType.READ)
   7:    public int getPropertyA() {
   8:      return config.propertyA;
   9:    }
  10:   
  11:    @PostConstruct 
  12:    private void init() {
  13:      // initialize configuration data
  14:      config = ...;
  15:    }
  16:  }

The @Lock(LockType.READ) annotation tells the container that any number of concurrent invocations can access getPropertyA() at the same time. This is the simplest case since this bean has immutable state. If it supported updates, it would look like this :


   1:  @Singleton
   2:  public class SharedConfig {
   3:            
   4:    private ConfigData config; 
   5:       
   6:    @Lock(LockType.READ)
   7:    public int getPropertyA() {
   8:      return config.propertyA;
   9:    }
  10:   
  11:    @Lock(LockType.WRITE)
  12:    public void update(...) {
  13:      // update state
  14:      ...
  15:    }
  16:   
  17:    @PostConstruct 
  18:    private void init() {
  19:      // initialize configuration data
  20:      config = ...;
  21:    }
  22:  }

Here, the container guarantees that an invocation on the update() method will only proceed when it can have exclusive access to the bean instance.

In BMC mode, the bean developer has full control over concurrency. The container passes all invocation threads directly through to the bean instance, just as in the Servlet programming model. It's the developer's responsibility to ensure the integrity of the instance state however possible, including through the use of Java SE level synchronization primitives. Here's the previous example using BMC mode :


   1:  @Singleton
   2:  @ConcurrencyManagement(ConcurrencyManagementType.BEAN)
   3:  public class SharedConfig {
   4:            
   5:    private ConfigData config; 
   6:       
   7:    synchronized public int getPropertyA() {
   8:      return config.propertyA;
   9:    }
  10:   
  11:    synchronized public void update(...) {
  12:      // update state
  13:      ...
  14:    }
  15:   
  16:    @PostConstruct 
  17:    private void init() {
  18:      // initialize configuration data
  19:      config = ...;
  20:    }
  21:  } 

This is an oversimplified example of BMC merely intended to show the required annotations and an example of Java SE level synchronization appearing directly in the bean class. Typically the locking would not be applied at the method level since that approach does not offer significant benefit over CMC mode. Much like the tradeoffs associated with using Bean Managed Transactions, Bean Managed Concurrency mode offers finer-grained control at the cost of added code complexity.

That's a brief introduction to Singletons. I'll be writing a follow-up post about how they can provide another piece of previously missing EJB component functionality : application startup and shutdown callbacks.

Thursday Dec 10, 2009

Final EJB 3.1 Specification and GlassFish v3 Now Available

I'm thrilled to announce that the final EJB 3.1 Specification has been approved! I'd like to thank the EJB 3.1 Expert Group for their extensive contributions over the last few years. And of course a heartfelt thanks to the EJB developer community for all the feedback, in its many forms, that helped produce the final outcome.

A complete implementation of EJB 3.1 is now available within GlassFish v3. I encourage you to download it and try out all the new ease-of-use enhancements and features. Here are a few additional EJB 3.1 resources :

As always, feel free to leave comments or requests for future enhancements here, or send them to jsr-318-comments@jcp.org

Friday Apr 03, 2009

JAX-RS and EJB

Many developers have asked about the relationship between JAX-RS (Java API for Restful Web Services) and Enterprise JavaBeans. The good news is that in Java EE 6, session beans can be implemented as JAX-RS resource or provider classes. The two work very well together thanks to JAX-RS flexibility in handling many kinds of resource classes, the EJB 3.1 no-interface view, and the ability to package enterprise beans directly in a .war.

One simple class functions as both a full-fledged JAX-RS resource and a stateless or singleton session bean. It can take advantage of all JAX-RS and EJB 3.1 functionality, including injection of JAX-RS context information, container-managed transactions, simple access to other managed EE resources such as JPA persistence contexts, etc.

See Paul Sandoz's blog for more details and a pointer to an early access implementation.

Wednesday Mar 11, 2009

EJB 3.1 Proposed Final Draft Now Available

I'm pleased to announce that the EJB 3.1 Proposed Final Draft is now available. We're well on our way towards finalizing what I'm sure will be a vastly improved version of Enterprise JavaBeans. The spec includes many clarifications to the requirements from the previous drafts, as well as some small feature improvements. Here are a few of the notable changes :

Improved portable Local Session Bean lookups

The EJB 3.1 Public Draft introduced portable global JNDI names for session beans. While the global syntax works great for Remote lookups, it is not ideal for dynamic lookups of Local session beans. We've gotten a lot of feedback that it's too cumbersome to have to declare an ejb-local-ref or @EJB annotation just to retrieve a session bean defined within the same module.

The problem with the portable global JNDI name syntax is that it requires knowing the module name and potentially the application name in order to make the lookup. To minimize these dependencies, we're adding JNDI syntaxes based on two new portable naming scopes called java:module and java:app.

java:module lookups are scoped to the module in which the lookup occurs. They allow session beans to be retrieved based only on the ejb-name.

java:app lookups are scoped to the application in which the lookup occurs. They allow session beans to be retrieved based only on the module name and the ejb-name.

For example, given the following Stateless session bean :

   1:  @Stateless 
   2:  public class HelloBean {
   3:     public String hello() { return "hello, world\\n"; }
   4:  }

Any code running within the same module as HelloBean can portably retrieve its reference as follows :

   1:  InitialContext ic = new InitialContext();
   2:  HelloBean hb = (HelloBean) ic.lookup("java:module/HelloBean");

Likewise, if HelloBean is packaged in hello.jar, any code running in a module within the same .ear can portably retrieve its reference using the string "java:app/hello/HelloBean".

See Section 4.4 for more details.

Timezone support for calendar-based timers

One of the limitations of calendar-based timers as defined in the Public Draft is that their schedules can only be specified relative to the time zone in which the application is deployed. That means if you want a calendar-based timeout to occur at a specific time in a given time zone, there's no easy way to do it.

The Proposed Final Draft addresses this by allowing an optional time zone ID to be associated with a calendar-based timer. In that case, all timeouts occur relative to the specified time zone. Time zones are supported no matter how the calendar-based timer is defined : programmatically, via annotation, or in ejb-jar.xml.

For example, the following code defines an automatic calendar-based timeout that occurs at 10 a.m. U.S. Eastern Time every day, independent of where the application itself is running :

   1:  @Schedule(hour="10", timezone="America/New_York")
   2:  public void timeout() { ... } 

See Section 18.2 for more details.

Spec-defined stateful session bean timeouts

Developers are always asking why there isn't a spec-defined way to specify the stateful session bean timeout value. Stateful session beans have always had the notion of a timeout, yet it has been left to the vendors to define the configuration for this value. The Proposed Final Draft defines a portable way to specify it.

   1:  @Stateful
   2:  @StatefulTimeout(value=10, unit=TimeUnit.MINUTES)
   3:  public class CartBean { ... }

@StatefulTimeout specifies the amount of time a stateful session bean can be idle (not receive any client invocations) before being eligible for removal by the container. The time unit is optional and defaults to MINUTES. Like all of our annotations, the stateful timeout metadata can also be specified in ejb-jar.xml.

See Section 4.3.12 for more details.


Please check out the spec and leave feedback here or at jsr-318-comments@jcp.org. Note that given where we are in the process the top priority is fixing spec bugs and problems with the APIs. Of course, we're always interested in hearing feature requests for future EJB versions :-)

Friday Nov 07, 2008

EJB 3.1 in GlassFish v3 Prelude

Now that the GlassFish v3 Prelude release is available it's a great time to try out some EJB 3.1 features that are being developed as part of the reference implementation. We have an EJB 3.1 module that provides early access implementations of the following functionality :

See Mahesh's blog for details on downloading the module through the Update Center and running a sample application.

Monday Oct 06, 2008

Portable Global JNDI Names

Dealing with session bean global JNDI names is a common source of frustration for EJB component developers. Global JNDI names have always been outside the scope of the specs. Even though most Java EE implementations take the same high-level approach to their use, the actual syntax is typically different for each product. This leads to developer confusion and requires additional configuration steps for each deployment environment. Portability issues are also common as developers mistakenly embed the vendor-specific global JNDI names in the source code.

We're planning to solve these problems by defining portable global JNDI names for session beans.

Let's take a look at a simple example. Here's a basic stateless session bean exposing a remote business interface :

   1:  @Stateless
   2:  public class FooBean implements FooRemote { ... }

The two most common client scenarios are :

a) Remote EJB dependency from a Java EE component in a different application

   1:  @EJB 
   2:  FooRemote foo;

Since the target bean resides outside the application, there is no standard way to tell the deployment environment how to resolve the @EJB dependency.

b) Remote access from a "stand-alone" (non Java EE) component

   1:  FooRemote foo = (FooRemote) 
   2:    new InitialContext().lookup("<global_jndi_name>");

In this case there is no standard string to use in the context lookup.

Our proposed solution is to define a standard global namespace that has a well-defined name for each session bean. For example, if FooBean were deployed as fooejb.jar, its standard global JNDI name would be "java:global/fooejb/FooBean".

The revised, now portable, client examples become :

a) Remote EJB dependency from a Java EE component in a different application

   1:  @EJB(mappedName="java:global/fooejb/FooBean")  
   2:  FooRemote foo;

Note that the existence of portable global JNDI names does not mean that the Java EE component environment should be bypassed. There are still many advantages to using @EJB or ejb-ref as a way to declare the caller's dependency on an enterprise bean. An important one is the option to move the global JNDI name mapping information to a descriptor so that it's not hard-coded.

b) Remote access from a "stand-alone" (non Java EE) component

   1:  FooRemote foo = (FooRemote) 
   2:    new InitialContext().lookup("java:global/fooejb/FooBean");

Non Java EE clients do not have access to a component environment so they must perform an explicit global lookup. The spec-defined global name at least ensures that the lookup string will be uniform across Java EE products.

The previous examples deals with the remote view, but the portable global JNDI names apply to session beans exposing Local and no-interface views as well. This is especially useful in conjunction with the new EJB 3.1 embeddable API.

More generally, the syntax for determining a session bean's portable global JNDI name is :

 java:global[/<app-name>]/<module-name>/<bean-name>

Application name and module name both default to the unqualified name of their respective bundle, minus the file extension. Each name will also be configurable via a standard deployment descriptor element. Application name only applies when the application is deployed in a .ear file. Bean name defaults to the unqualified name of the bean class, unless set as the name() attribute on the component-defining annotation or in the ejb-name element of ejb-jar.xml.

The spec will also define a variation of the global name syntax for identifying a particular client view of a session bean. This is useful for the case that a single session bean exposes multiple client views. The only difference is an additional field for the fully-qualified interface name (or bean-class type in the case of the no-interface view) :

 java:global[/<app-name>]/<module-name>/<bean-name>/<intf-name>

Wednesday Oct 01, 2008

Guide to the EJB 3.1 Public Draft

Now that the EJB 3.1 Public Draft is available, here's a list of its main ease-of-use improvements and features, along with their corresponding sections in the spec. This should make it easier to quickly find some of the most relevant material. While it's true that the spec is a bit, shall we say, on the "large" side, I think you'll find that most of the new content is concentrated in a relatively small number of pages. Happy reviewing :-)

  • The "no interface" Local view (3.4.4 , 4.9.8)
  • Portable global JNDI names (4.4)
  • Asynchronous session bean invocations (4.5)
  • Singleton session beans (4.8)
  • Startup / Shutdown callbacks (4.8.1, 4.8.2)
  • Calendar-based timer expressions (18.2.1)
  • Automatic timer creation (18.2.2)
  • Non-persistent Timers (18.2.3)
  • Deployment of EJB components directly in a .war without an ejb-jar (20.4)
  • EJB "Lite" -- a standard lightweight subset of the EJB API (21.1)
  • Embeddable EJB -- an API for executing EJB components within Java SE (Ch. 22)

EJB 3.1 Public Draft Now Available

I'm happy to announce that the EJB 3.1 Public Draft is now available. (Download it here) The Expert Group has been working hard to improve the spec since we released the Early Draft in February, driven in large part by the community feedback we've received. We encourage you to help us continue that effort by leaving review comments below or by sending email to jsr-318-comments@jcp.org. I'll be following up with a more detailed look at the content so stay tuned...

Tuesday Jul 29, 2008

Embeddable EJB

One of the most common requests we hear from Enterprise JavaBeans developers is for improved unit testing support. The two biggest issues they raise are :

  • Testing Local Session Beans is difficult since they're only accessible by way of the Remote EJB tier or the web tier.
  • Regardless of bean type, it would be simpler to allow client code to run in the same JVM as the components under test.

Some Java EE implementations have solved these problems by adding a Java SE execution mode in which clients instantiate EJB components within the same JVM. While this is a great start, more work is needed to raise the level of portability and ensure broader support.

We've been discussing this topic extensively in the EJB 3.1 Expert Group. Here's an early look at a proposed solution we're calling Embeddable EJB :

The Embeddable EJB API allows client code to instantiate an EJB container that runs within its own JVM and classloader. The client uses a spec-defined bootstrapping API to start the container and identify the set of enterprise bean components for execution.

The embeddable EJB container provides a managed environment with support for the same basic services that exist within a Java EE runtime : injection, access to a component environment, container-managed transactions, container-managed persistence contexts, etc. In general, enterprise bean components are unaware of the kind of managed environment in which they are running. This allows maximum reusability of bean components across a wide range of testing and deployment scenarios without significant rework.

Let's look at an example. Here's a simple Stateless session bean that uses Java Persistence to implement some bank account operations :

   1:  @Stateless
   2:  public class AccountBean {
   3:   
   4:    @PersistenceContext EntityManager em;
   5:   
   6:    public void createAccount(int acctId) {
   7:   
   8:      Account account = new Account(acctId);
   9:   
  10:      em.persist(account);  
  11:   
  12:    }
  13:    ... 
  14:  }

Note that this is just a normal stateless session bean. It exposes business methods through a no-interface view. The bean implementation uses injection, container-managed transactions, and Java Persistence. There is no special API it must use to be capable of embeddable execution.

Here is some test code to execute the bean in an embeddable container :

   1:   
   2:  // Instantiate an embeddable EJB container and search the
   3:  // JVM class path for eligible EJB modules or directories
   4:  EJBContainer ejbC = EJBContainer.createEJBContainer();
   5:   
   6:  // Get a naming context for session bean lookups
   7:  Context ctx = ejbC.getNamingContext();
   8:          
   9:  // Retrieve a reference to the AccountBean using a
  10:  // portable global JNDI name (more on this later!)  
  11:  AccountBean ab = (AccountBean) 
  12:      ctx.lookup("java:global/account/AccountBean");
  13:   
  14:  // Test the account
  15:   
  16:  Account a1 = ab.createAccount(1234);
  17:   
  18:  ...
  19:   
  20:  // Shutdown the embeddable container
  21:  ejbC.close();    
  22:   

Next we prepare the following three .jars :

  • account.jar
    An ejb-jar containing the AccountBean class and its associated persistence artifacts.

  • client.jar
    A .jar containing the test client class.

  • vendor.jar
    A vendor-provided .jar file containing the necessary system classes.

All that's left to do is start the JVM using a normal java command :

% java -cp account.jar:client.jar:vendor.jar com.acme.AccountTest

It's important that we support starting the JVM with a plain java command. Not only is it easily understood by developers but it ensures straightforward integration with existing test frameworks and IDEs. We also plan to support an "exploded" directory form of the ejb-jar to reduce the number of packaging steps.

There are more details to work out but we think this is a good first step. As always, let us know your feedback by leaving comments here or by sending email to jsr-318-comments@jcp.org.

Tuesday May 06, 2008

Preview Implementation of Some EJB 3.1 Features

The Reference Implementation for EJB 3.1 is being developed as part of the Glassfish project. A preview implementation of two new ease-of-use enhancements (simplified packaging and the "no-interface" view) is now available. See Mahesh's blog for the details. Give it a try and let us know your feedback.

Friday Mar 14, 2008

Simplified EJB Component Packaging

The EJB 3.0 Specification simplified many aspects of EJB component development. It reduced the number of required classes and interfaces, established intelligent defaults, and made the ejb-jar.xml file optional, to name just a few.

However, the specification still requires that all EJB components be packaged within an ejb-jar file. In many cases this restriction adds undue complexity to Java EE development. To remedy that, we're planning to allow EJB components to be packaged directly within a .war file, without the need for an ejb-jar.

Let's look at an example. Assume we have a simple Stateless Session Bean that exposes a no-interface view :

   1:  package com.acme;
   2:   
   3:  @Stateless
   4:  public class FooBean {
   5:    public void foo() { ... }
   6:  }

Normally, accessing this bean from a Servlet would require one .war, one ejb-jar, and an .ear file to wrap the two modules together. With the new packaging alternative, everything fits into a single .war :
$ jar tf foo.war 
WEB-INF/classes/com/acme/FooBean.class
WEB-INF/classes/com/acme/FooServlet.class
WEB-INF/web.xml

It's important to point out that the goal here is to remove an artificial packaging restriction, not to create a new flavor of EJB component that uses web container APIs. From an EJB component's perspective it still lives within the same managed runtime environment as before. This is important, as it keeps the programming model independent of packaging decisions.

Here are some more details about how the new packaging approach would likely be defined :

  • EJB component classes are packaged within WEB-INF/classes and/or in WEB-INF/lib.
  • EJB components share the same classloader as other classes in WEB-INF/classes and WEB-INF/lib.
  • EJB components share the .war's module-level component environment. For example, a resource-ref defined within web.xml would be visible to any EJB components in the .war.
  • EJB components have visibility to any persistence units defined within the .war.
  • ejb-jar.xml is optional. If needed, it is placed in WEB-INF/.
  • There are no special restrictions placed on a .war just because it contains EJB components. It can be deployed as a stand-alone .war or included within an .ear along with any number of other .wars or ejb-jars.
  • The full EJB feature set is available. For example, it would be possible to define a message-driven bean by placing a bean class annotated with @MessageDriven within WEB-INF/classes.

That's a quick overview of a new simplified alternative to EJB component packaging. Please post comments here or send them to our EJB 3.1 feedback alias.

Wednesday Mar 12, 2008

EJB 3.1 Presentation at JavaPolis 2007

I presented an overview of Enterprise JavaBeans 3.1 (JSR 318) last December at the JavaPolis '07 conference in Antwerp, Belgium. Here are the slides and video.
About

Ken Saks is the Spec Lead for Enterprise JavaBeans (EJB) 3.1 and a Senior Staff Engineer in the Java Platform, Enterprise Edition team at SUN.

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today