|
YOUR FEEDBACK Did you read today's front page stories & breaking news?
SYS-CON.TV |
TOP THREE LINKS YOU MUST CLICK ON Advanced Java Build to Spec!
Build to Spec!
By: Elizabeth Blair
Oct. 1, 2001 12:00 AM
While J2EE technology is designed to support portability, it's always possible to write nonportable code. In Part 2 of this series, we (the BluePrints development team) offer recommendations on how to avoid specific design, implementation, and deployment pitfalls that can compromise portability. A comprehensive collection of the J2EE BluePrints application programming model can be found at http://java.sun.com/j2ee/blueprints. This month, our recommendations are:
Always specify a unique context root for every Web application you deploy to avoid naming collisions with applications already deployed. The context root is the base path of a Web application, relative to the server's base URL. For example, if your server's base URL is http://j2eeserver.com:8000 and the context root is apps/myapp, then all components of the Web application will be accessed relative to http://j2eeserver.com:8000/apps/myapp. The <context-root> element of the Web application's deployment descriptor (web.xml) specifies the application context root. Server behavior can be unpredictable if two applications are deployed to the same context root since it isn't clear which application should receive an incoming request. Servers and deployment tools will differ in how they handle context root collisions. A good deployment tool will detect context root collisions at deployment time and allow the deployer to choose a different context root. Selecting a unique context root for every application will prevent this problem from ever occurring. For example:
App1.ear: war_runtime.xml
<web>The code snippets in the preceding example show how App1 and App2 specify unique <context-root> entries so that requests can be clearly channeled to the appropriate application Web page.
Store Enterprise Bean Handles or Remote References in HttpSession
Every enterprise bean remote reference extends EJBObject. A remote reference's method EJBObject.getHandle() returns a handle, which is a persistable reference to the object. A handle can be serialized and persisted, and then at some later time deserialized and converted back into a remote reference to the original bean (if the bean still exists). Some application developers believe that a handle is the only way to store a reference to an enterprise bean in HttpSession, but this isn't the case. In fact, an enterprise bean reference (acquired from a home interface create or finder method) can be stored directly in HttpSession without first converting it to a handle. A compatible application server that supports distributable servlets is required by the specification to correctly manage enterprise bean references stored in HttpSession. Therefore, remote references (that extend EJBObject) can be stored directly in HttpSession with no loss of portability. For more information refer to the J2EE Platform Specification 1.2, section 6.6.
New TagLibrary Format: J2EE 1.2
Here's an excerpt from a JSP 1.1 taglib.tld file:
<taglib>Here is the same snippet for JSP 1.2:
<taglib> <tlib-version>1.0</tlib-version> <jsp-version>1.2</jsp-version> <short-name>j2ee</short-name>Your application server will hopefully provide good migration tools that will update these files for you; otherwise, you may have to check and edit them manually. The samples used in this example are just a few of the JSP DTD tag name changes. See the relevant sections of the JSP 1.1 (section 5.3.5) and JSP 1.2 (Appendix C) specifications for details.
Always Import Classes Used in JSP Pages
The only packages that can portably be used without importing are java.lang.*, javax.servlet.*, javax.http.*, and javax.servlet.jsp.*. All other packages should be imported in the JSP page. JSP containers other than Tomcat may import classes beyond those required by the specification, but relying on the presence of those classes may make your JSP pages nonportable. See the section on the import keyword in the JSP 1.2 pfd 2 specification, section 2.10.1.1.
Never Throw Resource-Specific Exceptions from BMP Code
Bean providers should be especially careful to avoid including back-end resource-specific details in their components' interfaces since doing so may limit where the components might be used. One easily overlooked form of resource dependence is the set of exceptions a method may throw. BMP methods don't necessarily use a SQL database to manage their persistence, so SQLException doesn't belong in the BMP method signatures. Instead of throwing SQLException, define system- and application-level exceptions for the class and throw those exceptions in response to error conditions. The BluePrints program recommends the Data Access Object (DAO) design pattern ( http://java.sun.com/j2ee/blueprints/design_catalog/dao) to encapsulate a back-end resource, such as a SQL database. A DAO provides access to a system resource without reference to how that resource is implemented. For example, a DAO might offer methods to load, update, and delete a persistent object, and methods to set and get that object's properties, while hiding the implementation details of how those operations occur. The DAO can catch resource-specific exceptions and translate those exceptions to the custom system- or application-level exceptions described above. See Listing 1 for an example from the Java Pet Store. In method deleteAccount(), a SQLException is translated to an AccountDAOSysException, which extends java. lang.RuntimeException to indicate a system-level exception. It's worth noting that the Account bean indicates application-level errors with subclasses of AccountDAOAppException (such as AccountDAODBUpdateException). An application-level exception is typically thrown when a recoverable error has occurred, such as an incorrect user password. A system-level exception (like AccountDAOSysException above) is typically thrown when a nonrecoverable error has occurred, such as a database crash. Learn more about the differences between system- and application-level exceptions in Chapter 12 of the EJB specification.
Security: User Authentication
Isolating the code specific to an authentication mechanism makes porting easier since just that part of the code will need to be rewritten. See Scenario #3 on packaging from the JDJ "Build to Spec!" article (Vol 6. issue 7) for more information. For managing user authentication, consider using Java Authentication and Authorization Service. JAAS allows services to authenticate and enforce access controls on users. To learn more about JAAS, see the resources section at the end of this article. See also Table 6.2 of the J2EE 1.2 platform specification, where the J2EE security permission set for each type of component (application clients, applet clients, servlets/JSPs, EJBs, and so on) are defined.
Define Method Permissions When Security Roles Are Used in EJBs
There is a gray area in the J2EE 1.2 specification when it comes to defining the behavior of an unspecified method permission if security roles are used. The gray area has, legitimately, been interpreted inconsistently by container vendors. This means that EJB containers may not behave consistently for EJB methods with an unspecified method permission when security roles are used. For example, some container vendors may interpret unspecified method permissions to mean none, essentially an uncallable method for no user access; others may interpret unspecified method permissions to mean everybody for wide-open user access. In any case, if you use security roles and want the security behavior to be portable across container vendors, specify your intentions clearly with well-defined method permissions. The application developer may choose to create a role named everybody and then map this role to wide-open user access. This assumes the container has the ability to map the everybody role to a set of users. The everybody role could then be used in the ejb-jar.xml files for those methods where wide-open user access is allowed. For an example, see Listing 2. Refer to the J2EE 1.3 specification for the latest changes for using security roles and EJB method permissions.
Use of Security APIs:
The main reason is that there's no standard format for the return value of EJBContext.getCallerPrincipal().getName(). As of proposed final draft2, the EJB 2.0 specification mentions that calling methods "might, for example, use the name as a key to information in a database." In general this will work; however, there's a caveat that in complex security infrastructures this value might change. Here are some scenarios where this might be a problem:
"Hello <%= request.getUserPrincipal().getName() %>" Another possibility is as a log message in the EJB tier for auditing, for example: "8:15 AM: User " + ejbContext.getCallerPrincipal().getName() + " withdrew money." Until the return values are standardized from this API, its use to produce values that must be compatible with values that may be produced by other container vendors isn't a recommended portability practice. Look for this item to be addressed in future versions of the J2EE platform specification.
We Want to Hear from You
Resources
LATEST JAVA STORIES & POSTS
SUBSCRIBE TO THE WORLD'S MOST POWERFUL NEWSLETTERS SUBSCRIBE TO OUR RSS FEEDS & GET YOUR SYS-CON NEWS LIVE!
|
SYS-CON FEATURED WHITEPAPERS MOST READ THIS WEEK SPONSORED BY INFRAGISTICS
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||