Programming restrictions on EJB

Learn to write reliable and portable EJB 1.1 components

Enterprise JavaBeans (EJB) is a specification and architecture for the development and deployment of distributed server-side, transactional, and secure business application components. The EJB architecture is the basis and core of the Java 2 Enterprise Edition (J2EE), which defines an entire standardized application development architecture as well as a deployment environment. In this architecture, application developers focus on encapsulating the business logic and business rules and leave the infrastructural service-related issues or plumbing to the application container and server.

Further, the runtime properties of the application components pertaining to transactions, persistence, security, and so on are customizable in the deployment environment, using the highly flexible declarative approach. The architecture defines a container and server model — the container is the environment in which application component instances live and execute, while containers are in turn housed within a server. The J2EE platform thus provides a simplified development model, industrial-strength scalability, support for legacy integration, flexible deployment, application server and vendor independence, and generally tends to make proprietary application servers and proprietary distributed object frameworks almost archaic.

EJB roles and responsibilities

The EJB specification defines several standard roles and responsibilities as listed below:

  1. EJB Server provider provides the EJB application server, and it is an expert in distributed transaction management, system services, and so on.
  2. EJB Container provider provides the runtime environment for the EJB components’ instances as well as the deployment tools. EJB Server/Container providers are typically OS vendors, database vendors, and application server vendors. The EJB server and EJB container are assumed to be provided by the same vendor because no interfaces between them have been defined in the specification — both in the current EJB 1.1 (final version) as well as the EJB 2.0 public-draft version, which is currently under review.
  3. Bean provider, or EJB developer, develops EJB components that contain business logic and business functionality. The EJB developer provides for each EJB component: the EJB implementation containing all obligatory component-container contract methods, such as ejbCreate(), ejbRemove(), and so on, as well as the business methods; the Home interface; the Remote interface; and helper classes if necessary. The Home interface provides the signature for the methods that create, remove, and find EJB instances. The Remote interface defines the signatures for the business methods.
  4. Application Assembler takes a set of EJB components developed by the Bean provider and assembles them into a complete J2EE application.
  5. Deployer is an expert in the target production environment in which the application is to be deployed. The deployer installs the application components on the application server and configures their transactional, data persistence, and security aspects. Thus, you can declaratively address and manage complex issues such as transactions, concurrency, persistence, and security.
  6. Systems Administrator is responsible for the server’s configuration and administration, runtime monitoring, and load balancing.
  7. Application Client/User Interface developer is responsible for the user interface and presentation logic.

The focus of this article is on the Bean provider/EJB developer and the programming restrictions that apply to the EJB components’ implementation code.

Restrictions on EJB components

The EJB developer must not program any systems-level services into the EJB component implementation code. EJB component providers/developers should be aware of and strictly follow certain restrictions in the interest of developing reliable and portable EJB components.

The following is a list of Java features that you should avoid, hence restricting their use in your EJB components’ implementation code:

  1. Using static, nonfinal fields. Declaring all static fields in the EJB component as final is recommended. That ensures consistent runtime semantics so that EJB containers have the flexibility to distribute instances across multiple JVMs.
  2. Using thread synchronization primitives to synchronize multiple instance execution. By avoiding that feature, you allow the EJB container flexibility to distribute instances across multiple JVMs.
  3. Using AWT functionality for keyboard input/display output. That restriction exists because server-side business components are meant to provide business functionality that excludes user interface and keyboard I/O functionality.
  4. Using file access/java.io operations. EJB business components are meant to use resource managers such as JDBC to store and retrieve application data rather than the file system APIs. Also, deployment tools provide the facility for storing environment entry elements (env-entry) into the deployment descriptor, so that EJB components can perform environment entry lookups in a standardized manner via the environment-naming context. Thus, the need to use file system-based property files is mostly eliminated.
  5. Listening to or accepting socket connections, or using a socket for multicast. EJB components are not meant to provide network socket server functionality; however, the architecture lets EJB components act as a socket client or RMI clients and thus communicate with code outside the container’s managed environment.
  6. Using the Reflection API to query classes that are not otherwise accessible to the EJB component due to Java’s security rules. That restriction enforces Java platform security.
  7. Attempting to create or obtain a class loader, set or create a new security manager, stop the JVM, change the input, output, and error streams. That restriction enforces security and maintains the EJB container’s ability to manage the runtime environment.
  8. Setting the socket factory used by the URL’s ServerSocket, Socket, or stream handler. By avoiding that feature, you also enforce security and maintain the EJB container’s ability to manage the runtime environment.
  9. Starting, stopping, or managing threads in any way. That restriction eliminates the possibility of conflicts with the EJB container’s responsibilities of managing locking, threading, and concurrency issues.
  10. By restricting your use of features 10-16, you aim to plug potential security holes:

  11. Reading or writing a file descriptor directly.
  12. Obtaining security policy information for a particular code source.
  13. Loading native libraries.
  14. Accessing packages and classes that the usual rules of Java make unavailable.
  15. Defining a class in a package.
  16. Accessing or modifying security configuration objects (Policy, Security, Provider, Signer, and Identity).
  17. Using the subclass and object substitution features of the Java Serialization protocol.
  18. Passing the this reference as an argument or returning the this reference as a result. Instead, you must use the result of the getEJBObject() available in SessionContext or EntityContext.

Java 2 Platform Security policy

The restricted features listed above are, in fact, standard and powerful features of the Java programming language and the Java 2 Standard Edition (J2SE). The EJB container is allowed to make some or all of the restricted features from the J2SE unavailable to the EJB components — by using the J2SE security mechanism rather than by subsetting the J2SE API set.

The Java 2 Platform Security policy for the standard EJB container of the EJB 1.1 specification defines the security permission sets that concur with the programming restrictions on EJB components. According to the policy, several permissions such as java.io.FilePermission, java.net.NetPermission, java.io.reflect.ReflectPermission, and java.lang.security.SecurityPermission are denied in order to enforce the programming restrictions listed earlier.

Some EJB containers may not enforce the restrictions with the expectation that the EJB developer will either adhere to the programming restrictions or violate them at his or her own risk. EJB components that violate those restrictions, by relying on fewer or more permissions than the standard set, will at the very least not be portable across EJB containers. In addition, indeterminate and unpredictable runtime problems could lie hidden in the code. That’s all the more reason for EJB component developers to be aware of those programming restrictions and take special care to adhere to them.

Any violations of those programming restrictions within the EJB implementation code will not be detected at the time of compilation since those features are, after all, an integral part of the Java language and J2SE.

Those restrictions apply to EJB components as well as helper/access classes used by the EJB components. J2EE applications are packaged using the Java Archive (jar) file format into a file with an .ear extension (ear stands for Enterprise Archive). The ear file is the standard file format for delivering an application to the deployer. The ear file consists of EJB components in one or more ejb-jar files, and possibly library jar files on which the ejb-jars may depend. All code in that ear file is considered application code and is subject to the programming restrictions and permission sets.

A future version of the specifications might mandate the ability/facility to customize the security permissions via the deployment tools. That way specific permissions may be granted to a component based on merit and requirements in a standardized way such as permission to read a file in the file system. Some EJB container/server products may currently provide, within their deployment tools, the facility to grant fewer or more permissions with respect to the standard permissions, but that is not required by the EJB 1.1 (as well as 2.0 draft) specification.

Understanding restrictions

The EJB container is the runtime environment in which EJB component instances can live and execute. The EJB container provides the EJB component instances with services such as transaction management, security, persistence, resource access, and client connectivity. The container is also responsible for the EJB component instances’ complete life cycle management, scalability issues, and concurrency. The EJB components are thus housed within a managed execution environment, namely the container.

The EJB container is an intermediary between your EJB component and the outside world. It provides the client-connectivity service that allows the application clients to access and avail of functionality provided by your EJB components. The EJB container interposes between every client method invocation on an enterprise Bean object via the bean’s Remote and Home interface.

The EJB container is also the intermediary between your EJB component and access to various resources and services. Because the container interposes between the application components and the J2EE services, it can transparently inject services defined by the components’ deployment descriptors such as declarative transaction management, security, persistence, concurrency, and state management.

The container also manages resources and optimizes and pools various resources. Thus, every connection to a resource manager used by an EJB component is obtained via the EJB container. The J2EE container/server must provide certain resource factories, which the application components will use to access resources. Application components must not access resources directly but via the container.

A resource is an object that encapsulates access to a resource manager, while a resource factory is an object that is used to create resources. For example, a JDBC connection represented by an object that implements the java.sql.Connection interface is a resource that provides access to a database management system, and an object that implements the javax.sql.DataSource interface is a resource factory for such JDBC connections. Similarly, there are resource factories defined for obtaining JMS, JavaMail, and URL connections. No other resource factories beyond those related to JDBC, JMS, JavaMail, and URL connections are currently defined.

(The J2EE Connector Architecture, which is currently under public draft review, is expected to be included in future versions of the J2EE specification. The connector architecture defines standard resource adapters and contracts pertaining to connection, transaction, and security management, so the application servers may be plugged with heterogeneous Enterprise Information Systems, including ERP (such as SAP R/3), mainframe transaction processing systems, and database systems in a standard and uniform manner.)

Because the container is completely responsible for the EJB components’ life cycle, concurrency, resource access, security, and so forth, the possibilities of conflicts with the container’s own locking and concurrency management need to be eliminated. Some of the restrictions endeavor to plug potential security holes. Besides the issues of conflict with the container’s responsibilities and security, EJB components are meant to focus on business logic only, and they rely on services provided by the EJB container rather than deal with low-level system level issues directly.

Portability issues

In general, the cross container portability of any EJB component is inversely related to:

  1. Its dependency on usage of restricted features that are not enforced on a particular EJB container.
  2. Its dependency on nonstandard services availed from the container.

To guarantee portability and consistent behavior of the EJB component, you should test EJB components, using a container that has the security settings according to the Java 2 Platform Security policy sets, which are consistent with enforcing the programming restrictions.

Conclusion

EJB component developers should be aware of the recommended programming restrictions on EJB components, understand their significance, and follow them in the interest of component reliability and portability. Because those programming restrictions prevent you from using certain standard Java language features, any violation of them will not be known at compile time. It is also not mandatory for the EJB container to enforce those restrictions. That’s all the more reason for you to take special care to adhere to those programming restrictions, which have been stipulated as an item in the component contract, and are important for building reliable and portable EJB components.

Sanjay Mahapatra is a Sun-certified Java
programmer (1.1), developer (Java 2), and architect (Java 2). He
currently works for Cook Systems
International, a consulting and solutions company.

Source: www.infoworld.com