John TK's profilej0Hn:cH1n:7hA0:K3n9@w3bL...PhotosBlogLists Tools Help

John TK - Chin -

Lists

j0Hn:cH1n:7hA0:K3n9@w3bL09ALA71cAL

Luke 1:37 /// 1Mp05518L3 I5 n07H1n9 ! ///
September 27

Macau

http://www.macautourism.gov.mo/pt/index.php
August 17

reverse proxy

A reverse proxy is a proxy server that is installed in the neighborhood of one or more webservers. All traffic coming from the Internet and with destination one of the webservers is going through the proxy server. There are several reasons for installing reverse proxy servers:

  • Security: the proxy server is an additional layer of defense and therefore protects the webservers further up the chain
  • Encryption / SSL acceleration: when secure websites are created, the SSL encryption is often not done by the webserver itself, but by a reverse proxy that is equipped with SSL acceleration hardware. See Secure Sockets Layer.
  • Load distribution: the reverse proxy can distribute the load to several webservers, each webserver serving its own application area. In such a case, the reverse proxy may need to have to rewrite the URLs in each webpage (translation from externally known URLs to the internal locations)
  • Serve/cache static content: A reverse proxy can offload the webservers by caching static content like pictures and other static graphical content
  • Compression: the proxy server can optimize and compress the content to speed up the load time.

Reverse proxy is, as the name suggests, similar to "proxying backwards".

Rather than have a bunch of clients funnel into one proxy server, you would
actually have a bunch of servers funnel into one proxy server.

Consider an environment where you have 10 web servers handling critical
data. You can put all these servers behind a firewall, so that your
critical data remains secure. You then create a reverse proxy server which
handles all the requests, and depending on the path the request is then
forwarded to one of the actual web servers. Further, your web servers don't
need to have routable IP addresses this way -- just one for the proxy.

In this way, your proxy server would:

take requests for http://www/dir1/ and forward the requests to server 1
take requests for http://www/dir2/ and forward them to server 2,
and so on.

The web servers could have very tight access control and handle requests
ONLY from the proxy server.

Other interesting scenarios are possible. Consider

http://www/ny/ which forwards requests to the NY based-web server.
and
http://www/ca/ which forwards requests to the CA based server.

A typical usage of a reverse proxy is to provide Internet users access to a server that is behind a firewall. Reverse proxies can also be used to balance load among several back-end servers, or to provide caching for a slower back-end server. In addition, reverse proxies can be used simply to bring several servers into the same URL space.

Reference

http://www.phptr.com/articles/printerfriendly.asp?p=169534


August 05

generic sh .profile

# Global profile (for sh/ksh/bash)
#

# Make sure '.' is in PATH
if [ "`echo $PATH | /usr/xpg4/bin/grep -E '^\.:|^\.$|:\.:|:\.$'`" ]; then
PATH="$HOME/bin:$PATH:/usr/local/bin:/usr/X/bin:/usr/openwin/bin"
else
PATH="$HOME/bin:$PATH:/usr/local/bin:/usr/X/bin:/usr/openwin/bin:."
fi

# New files get 640 permissions
umask 0026

# Setup terminal if we are on one
if [ "`tty`" != 'not a tty' ]; then
stty -istrip
stty erase ^H
fi

# Setup shell variables
if [ "$SHELL" = '/bin/bash' ]; then
#PS1='\u:\w\$ '
PS1='\u@\h:\w:$ '
else
PS1="`/usr/ucb/whoami`$ "
fi
EDITOR=vi; export EDITOR

# Aliases
alias ps='/usr/bin/ps'

June 14

.NET Remoting Versus Web Services

With the advent of .NET and the .NET Framework, Microsoft introduced a set of new technologies in the form of Web services and .NET remoting. .NET remoting and ASP.NET Web services are powerful technologies that provide a suitable framework for developing distributed applications. It is important to understand how both technologies work and then choose the one that is right for your application.

The Web services technology enables cross-platform integration by using HTTP, XML and SOAP for communication thereby enabling true business-to-business application integrations across firewalls. Because Web services rely on industry standards to expose application functionality on the Internet, they are independent of programming language, platform and device.

Remoting is .a technology that allows programs and software components to interact across application domains, processes, and machine boundaries. This enables your applications to take advantage of remote resources in a networked environment.

Both Web services and remoting support developing distributed applications and application integration, but you need to consider how they differ before choosing one implementation over the other. In this article, I will show the differences between these two technologies. I will present samples for each type of implementation and identify when to use which technology.

DCOM

If you are a real Microsoft platform developer then you have done some work on COM and interface based components. When it comes to distributing your program logic, you are almost tied to Distributed COM (DCOM).

DCOM is a very proprietary RPC-based communication protocol for COM-based distributed component architectures. Even though DCOM allows us to create scalable and reliable architectures in the Intranet environment, there are a lot of problems with DCOM when you try to integrate with different platforms and technologies in an Internet environment.

A Look at .NET Remoting

.NET Remoting uses a flexible and extremely extensible architecture. Remoting uses the .NET concept of an Application Domain (AppDomain) to determine its activity. An AppDomain is an abstract construct for ensuring isolation of data and code, but not having to rely on operating system specific concepts such as processes or threads. A process can contain multiple AppDomains but one AppDomain can only exist in exactly one process. If a call from program logic crosses an AppDomain boundary then .NET Remoting will come into place. An object is considered local if it resides in the same AppDomain as the caller. If the object is not in the same appdomain as the caller, then it is considered remote.

In .NET remoting, the remote object is implemented in a class that derives from System.MarshalByRefObject. The MarshalByRefObject class provides the core foundation for enabling remote access of objects across application domains. A remote object is confined to the application domain where it is created. In .NET remoting, a client doesn't call the methods directly; instead a proxy object is used to invoke methods on the remote object. Every public method that we define in the remote object class is available to be called from clients.

When a client calls the remote method, the proxy receives the call, encodes the message using an appropriate formatter, then sends the call over the channel to the server process. A listening channel on the server appdomain picks up the request and forwards it to the server remoting system, which locates and invokes the methods on the requested object. Once the execution is completed, the process is reversed and the results are returned back to the client.

Out of the box, the remoting framework comes with two formatters: the binary and SOAP formatters. The binary formatter is extremely fast, and encodes method calls in a proprietary, binary format. The SOAP formatter is slower, but it allows developers to encode the remote messages in a SOAP format. If neither formatter fits your needs, developers are free to write their own and plug it in as a replacement.

Different Types of Remote Objects

The remoting infrastructure allows you to create two distinct types of remote objects.

  1. Client-activated objects - A client-activated object is a server-side object whose creation and destruction is controlled by the client application. An instance of the remote object is created when the client calls the new operator on the server object. This instance lives as long as the client needs it, and lives across one to many method calls. The object will be subject to garbage collection once it's determined that no other clients need it.

  2. Server-activated objects - A server-activated object's lifetime is managed by the remote server, not the client that instantiates the object. This differs from the client-activated object, where the client governs when the object will be marked for finalization. It is important to understand that the server-activated objects are not created when a client calls New or Activator.GetObject. They are rather created when the client actually invokes a method on the proxy. There are two types of server activated objects. They are:
    • Single call . Single-call objects handle one, and only one, request coming from a client. When the client calls a method on a single call object, the object constructs itself, performs whatever action the method calls for, and the object is then subject to garbage collection. No state is held between calls, and each call (no matter what client it came from) is called on a new object instance.

    • Singleton - The difference in a singleton and single call lies in lifetime management. While single-call objects are stateless in nature, singletons are stateful objects, meaning that they can be used to retain state across multiple method calls. A singleton object instance serves multiple clients, allowing those clients to share data among themselves.

A Look At ASP.NET Web Services

With the arrival of .NET, creating an ASP.NET Web service is a breezy experience with the .NET framework taking away all the complexities in creating and consuming Web services. To create a Web service, all you need to do is create a Web service class that derives from the System.Web.Services.WebService class and decorate the methods (that you want to expose as Web services) with the WebMethod attribute. Once this is done, these methods can be invoked by sending HTTP requests using SOAP.

Consuming a Web service is very straightforward too. You can very easily create a proxy class for your Web service using either wsdl.exe utility or the Add Web Reference option in VS.NET. The Web service proxy hides all the network and marshaling plumbing from the application code, so using the Web service looks just like using any other local object.



Click here for larger image

As you can see from the above diagram, the client proxy receives the request from the client, serializes the request into a SOAP request which is then forwarded to the remote Web service. The remote Web service receives the SOAP request, executes the method, and sends the results in the form of a SOAP response to the client proxy, which deserializes the message and forwards the actual results to the client.

Now that we have understood the basic concepts of .NET remoting and Web services, let us identify the differences between these two technologies. For this, I present different factors such as performance, state management, etc and then identify which technology to use in what situations.

Performance

In terms of performance, the .NET remoting plumbing provides the fastest communication when you use the TCP channel and the binary formatter. In the case of Web services, the primary issue is performance. The verbosity of XML can cause SOAP serialization to be many times slower than a binary formatter. Additionally, string manipulation is very slow when compared to processing the individual bits of a binary stream. All data transported across the wire is formatted into a SOAP packet. However if your Web service performs computation intensive operations, you might want to consider using caching to increase the performance of your Web service on the server side. This will increase the scalability of the Web service, which in turn can contribute to the increase in performance of the Web service consumers. A remoting component, using the TCP channel and the binary formatter, provides the greatest performance of any remoting scenario, primarily because the binary formatter is able to serialize and deserialize data much faster.

If you use .NET remoting with a SOAP formatter, you will find that the performance provided by ASP.NET Web services is better than the performance provided by NET remoting endpoints that used the SOAP formatter with either the HTTP or the TCP channel. However the .NET remoting provides clear performance advantages over ASP.NET Web services only when you use TCP channels with binary communication.

State Management

Web services are a stateless programming model, which means each incoming request is handled independently. In addition, each time a client invokes an ASP.NET Web service, a new object is created to service the request. The object is destroyed after the method call completes. To maintain state between requests, you can either use the same techniques used by ASP.NET pages, i.e., the Session and Application objects, or you can implement your own custom solution. However it is important to remember that maintaining state can be costly with Web services as they use extensive memory resources.

.NET remoting supports a range of state management options that you can choose from. As mentioned before, SingleCall objects are stateless, Singleton objects can share state for all clients, and client-activated objects maintain state on a per-client basis. Having three types of remote objects (as opposed to one with Web services) during the design phase helps us create more efficient, scalable applications. If you don't need to maintain state, use single-call objects; if you need to maintain state in a small section of code, use single call and singletons together. The ability to mix and match the various object types facilitates creation of solid architectural designs.

Security

.NET remoting plumbing does not provide out of the box support for securing cross-process invocations. However a .NET remoting object hosted in IIS, can leverage all the same security features provided by IIS. If you are using the TCP channel or the HTTP channel hosted in a container other than IIS, you have to implement authentication, authorization and privacy mechanisms yourself.

Since ASP.NET Web services are hosted, by default, in IIS, they benefit from all the security features of IIS such as support for secure communication over the wire using SSL, authentication and authorization services.

Reliability

.NET remoting gives you the flexibility to host remote objects in any type of application including a Windows Form, a managed Windows Service, a console application or the ASP.NET worker process. If you host your remote objects in a windows service, or a console application, you need to make sure that you provide features such as fault tolerance within your hosting application so that the reliability of the remote object is not compromised. However if you do host remote objects in IIS, then you can take advantage of the fact that the ASP.NET worker process is both auto-starting and thread-safe. In the case of ASP.NET Web services, reliability is not a consideration as they are always hosted in IIS, making it easy for them to take advantage of the capabilities provided by IIS.

Extensibility

Both the ASP.NET Web services and the .NET remoting infrastructures are extensible. You can filter inbound and outbound messages, control aspects of type marshaling and metadata generation. .NET remoting takes extensibility to the next level allowing you to implement your own formatters and channels.

Since ASP.NET Web services rely on the System.Xml.Serialization.XmlSerializer class to marshal data to and from SOAP messages at runtime, we can very easily customize the marshaling by adding a set of custom attributes that can be used to control the serialization process. As a result, you have very fine-grained control over the shape of the XML being generated when an object is serialized.

Ease of programming and deployment

In this section, we will consider a simple remoting object and an ASP.NET Web service to understand the complexities involved in creating and consuming them. We will start off by creating a simple remote object.

Creating a remote object

Creating a remoting object is a simple process. To create a remote object, you need to inherit from MarshalByRefObject class. The following code shows a remotable class.

using System;
namespace RemoteClassLib
{
public class MyRemoteObject : System.MarshalByRefObject
{
public MyRemoteObject()
{
Console.WriteLine("Constructor called");
}

public string Hello(string name)
{
Console.WriteLine("Hello Called");
return "Hello " + name;
}
}
}

The above code is very simple and straightforward. We start off by defining a class that inherits from MarshalByRefObject. After that we add code to the constructor of the class to write out a message to the console. Then we have a method named Hello that basically takes a string argument and appends that with the string and returns the concatenated value back to the caller. Once the remote object is created, the next step is to create a host application that hosts the remote object. For the purposes of this article, we will create a console application that reads the details of the remote object from its configuration file.

using System;
using System.Runtime.Remoting;

namespace RemoteClassLibServer
{
class RemoteServer
{
[STAThread]
static void Main(string[] args)
{
RemotingConfiguration.Configure(
"RemoteClassLibServer.exe.config");
Console.WriteLine("Press return to Exit");
Console.ReadLine();
}
}
}

In the main method, we just read the configuration settings from the configuration file using the RemotingConfiguration.Configure method and wait for the client applications to connect to it.

The configuration file used by the above hosting application looks like the following. In the configuration file, we specify that we want to expose the remote object using the TCP channel by using the channel element.

<?xml version="1.0" encoding="utf-8" ?> 
<configuration>
<system.runtime.remoting>
<application name="RemoteClassLibServer">
<service>
<wellknown mode="SingleCall"
type="RemoteClassLib.MyRemoteObject,RemoteClassLib"
objectUri="MyRemoteObject">
</wellknown>
</service>
<channels>
<channel ref="tcp server" port="9000"/>
</channels>
</application>
</system.runtime.remoting>
</configuration>

Once the hosting application is started, then client applications can start creating instances of the remote object and invoke its methods. In the next section, we will understand the processes involved in creating an ASP.NET Web service.

Creating an ASP.NET Web Service

As mentioned before, creating an ASP.NET Web service is pretty easy in VS.NET. Select the ASP.NET Web Service template using Visual Studio.NET New Project dialog box. Enter the name of the project and click OK to create the project. Once the project is created, modify the default service1.asmx file to look like the following.

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Web;
using System.Web.Services;

namespace XmlWebServicesExample
{

public class Service1 : System.Web.Services.WebService
{
public Service1()
{
}

[WebMethod (EnableSession=true)]
public string HelloWorld()
{
return "Hello World";
}
}
}

As you can see from the above, the Web service class named Service1 is derived from System.Web.Services.WebService. Inheriting from the WebService class is optional and it is used to gain access to common ASP.NET objects like Application, Session, User, and Context. Then we also add a method named HelloWorld that basically returns a simple string back to the callers of the Web service. In the WebMethod attribute of the HelloWorld method, we also specify that we want to enable session state for our ASP.NET Web service by setting the EnableSession attribute to true.

Creating the consumer for the ASP.NET Web Service

You can consume the Web service by using the Add Web Reference option in VS.NET to create a proxy for the Web service. When you create a Web reference, the VS.NET IDE creates a proxy for you based on the WSDL file published by the Web service. Once the proxy is generated, you can treat the proxy class methods as if they are the actual Web service methods. At runtime, when the proxy class methods are invoked, they will connect to the actual Web service, invoke the Web service method, retrieve the results returned by the Web service and hand it back to the consumers. The following screenshot shows how to use the Add Web Reference option to create a proxy for the Web service.

 



Click here for larger image

So far, we have seen the steps involved in creating a .NET remoting object and an ASP.NET Web service. As can be seen from the above code, ASP.NET Web services are very easy-to-create. Consuming ASP.NET Web service is also a very simple process due to the excellent Web service support provided by Visual Studio.NET. With .NET remoting, you need to create the remote object first and then write a hosting application (assuming that you are not using IIS) to expose that remote object. You also need to make sure that the information about the remote object is retrieved from the configuration file to allow for extensibility in the future. If you all these factors into consideration, you will agree that .NET remoting objects are complex to develop and deploy.

Type Fidelity

ASP.NET Web services favor the XML schema type system, and provide a simple programming model with broad cross-platform reach. .NET remoting favors the runtime type system, and provides a more complex programming model with much more limited reach. This essential difference is the primary factor in determining which technology to use.

Putting it all together

So far, we have looked at the differences between these two technologies. Let us summarize the difference in a table.

  ASP.NET Web Services .NET Remoting
Protocol Can be accessed only over HTTP Can be accessed over any protocol (including TCP, HTTP, SMTP and so on)
State Management Web services work in a stateless environment Provide support for both stateful and stateless environments through Singleton and SingleCall objects
Type System Web services support only the datatypes defined in the XSD type system, limiting the number of objects that can be serialized. Using binary communication, .NET Remoting can provide support for rich type system
Interoperability Web services support interoperability across platforms, and are ideal for heterogeneous environments. .NET remoting requires the client be built using .NET, enforcing homogenous environment.
Reliability Highly reliable due to the fact that Web services are always hosted in IIS Can also take advantage of IIS for fault isolation. If IIS is not used, application needs to provide plumbing for ensuring the reliability of the application.
Extensibility Provides extensibility by allowing us to intercept the SOAP messages during the serialization and deserialization stages. Very extensible by allowing us to customize the different components of the .NET remoting framework.
Ease-of-Programming Easy-to-create and deploy. Complex to program.

Though both the .NET Remoting infrastructure and ASP.NET Web services can enable cross-process communication, each is designed to benefit a different target audience. ASP.NET Web services provide a simple programming model and a wide reach. .NET Remoting provides a more complex programming model and has a much narrower reach.

As explained before, the clear performance advantage provided by TCPChannel-remoting should make you think about using this channel whenever you can afford to do so. If you can create direct TCP connections from your clients to your server and if you need to support only the .NET platform, you should go for this channel. If you are going to go cross-platform or you have the requirement of supporting SOAP via HTTP, you should definitely go for ASP.NET Web services.

Combination of .NET Remoting and ASP.NET Web Services in Action



Click here for larger image

So far, we have understood how the .NET remoting and ASP.NET Web services technologies differ in implementation. We have also had a detailed look at different factors to understand what technology to choose in what situation. Even though these two technologies are meant for different purposes, there are times where you will be able to use the combination of these technologies in your application. For example, in an application scenario where you are trying to address the needs of both internet and intranet clients, you might consider using both .NET remoting and Web services as shown in the above diagram. For the intranet .NET clients, you can use .NET remoting to enable cross appdomain communication. For the internet clients, you can expose the same functionality as Web services, allowing client applications running in different platforms to take advantage of the Web service.

Conclusion

Both the .NET remoting and ASP.NET Web services are powerful technologies that provide a suitable framework for developing distributed applications. It is important to understand how both technologies work and then choose the one that is right for your application. For applications that require interoperability and must function over public networks, Web services are probably the best bet. For those that require communications with other .NET components and where performance is a key priority, .NET Remoting is the best choice. In short, use Web services when you need to send and receive data from different computing platforms, use .NET Remoting when sending and receiving data between .NET applications. In some architectural scenarios, you might also be able to use.NET Remoting in conjunction with ASP.NET Web services and take advantage of the best of both worlds.


June 09

EJB 3.0

EJB 3.0

At the present time, only the EJB 3.0 (Summer 2004 Early Draft Specification, http://jcp.org/aboutJava/communityprocess/edr/jsr220/index.html) has been made available. It is intended to obtain feedback from the community, but some probable aspects of the final release (including the clear influence of Hibernate 2.x for relational persistence) are already apparent.

Let's start by highlighting some of the similarities between EJB 3.0 and Hibernate 2.x. First and foremost, EJB 3.0 now bases container-managed persistence on plain old Java objects (POJO) with annotations, much like Hibernate's POJO + mapping file approach. From there, Hibernate's SessionManager and Session have been combined into a single EJB EntityManager class. EJB 3.0 now includes a Query class which allows for page control, similar to that of Hibernate. You are expected to mark one end of an association as inverse. And so on.

Some of the differences between Hibernate and EJB 3.0 are a natural outgrowth of the reliance of EJB 3.0 on Java 2 Standard Edition 5.0 (J2SE 5.0). For example, there is no notion of a Hibernate Configuration class, because EJB 3.0 relies on J2SE 5.0 annotations in lieu of external XML files. Extensions to EJBQL make it look more like HQL, including support for named parameters, fetch, bulk update, and bulk delete. Collection semantics go beyond the support provided in Hibernate, leveraging J2SE 5.0 generics (see JSR 14, http://jcp.org/en/jsr/detail?id=14, for more information on generics).

Some features of EJB 3.0 go significantly beyond what is offered by Hibernate 2.x. These include:

  • A defined distributed object environment.

  • Session, Message, and Entity object distinctions.

  • Additional object semantics and life cycles beyond object/relational persistence.

  • Security permissions (including method-level security).

  • Integrated resource-dependency references.

  • Integrated support for exposing objects as Web services (JSR 181).

  • A fully defined formal BNF description of the query language (important for robust parser implementations).

From the author's perspective, one of the most interesting advantages of EJB 3.0 as compared to Hibernate 2.1 HQL is the presence of a formal BNF for EJBQL. Backus Naur Form (BNF), as described at http://cui.unige.ch/db-research/Enseignement/analyseinfo/AboutBNF.html, is a formal description of a programming language. By providing a BNF, users can expect to see multiple parsers for a single language, allowing for richer and more innovative tools and solutions. For example, providing a BNF makes it much easier to produce a correct grammar for JavaCC, https://javacc.dev.java.net/. This in turn makes it much easier to produce alternative implementations for EJB 3.0 and to obtain rich support from toolsfor example, automatic type-ahead in a text editor.

For a Hibernate developer, the most shocking change when moving to EJB 3.0 is likely to be the reliance on annotations to provide persistence metadata. Simply put, EJB 3.0 development with annotations (per JSR 175, http://jcp.org/en/jsr/detail?id=175) is most similar to Hibernate development with XDoclet (as described in Chapter 3). This eliminates the need for separate XML configuration files because the information is encoded directly in the class files. The formal annotation specification (combined with solid tool support) should alleviate some problems with the current, error-prone nature of XDoclet development, but concerns about embedding database configuration information in Java source remain. The tremendous simplification of the development process may prove able to manage these concerns.

 

 

Java/Database Integration Solutions

Java/Database Integration Solutions

Hibernate represents merely one approach to object/relational mapping. Other programming languages and platforms offer a variety of other options, some similar to Hibernate, others radically different. Focusing on the Java world, here are a few of the popular alternatives.

Enterprise JavaBeans (EJB) 2.X

At the core of the J2EE specification, EJB 2.X attempts to provide a much broader set of features and functionality than Hibernate, at the price of a less robust core persistence model. The portion of J2EE/EJB 2.X most comparable to Hibernate is called container-managed entity persistence (CMP). Typically, CMP describes a system in which the J2EE server manages a single-entity bean class per table with individual-entity bean objects representing individual records. Conceptually, entity beans managed by the J2EE server include sophisticated functionality, such as complex transaction management, distributed caching, and much more. The alternative is bean-managed persistence, in which developer code is used to handle interaction with a database.

While EJB 2.X is suitable for certain large-scale enterprise applications, some developers find it difficult to work with. Most EJB 2.X systems involve a considerable amount of code generation and the need to master a complex suite of terminology. In particular, the implementation of the container-managed persistence layer and other components varies greatly between different application servers, making migration between projects that rely on container-managed persistence difficult. A popular use of Hibernate is as a persistence layer while working within the larger EJB 2.X environmentin effect, Hibernate serves as a replacement for container-managed persistence while leveraging the other portions of the EJB 2.X specification. This allows you to take advantage of many of the powerful features of your J2EE server without worrying about the portability of your object/relational layer.

Enterprise JavaBeans (EJB) 3.0

With an early draft specification first released in mid-2004, EJB 3.0 promises a persistence mechanism very similar to Hibernate. This is not surprising; the key developer of Hibernate was heavily involved in crafting the EJB 3.0 specification. Throughout this text, areas of similarity between EJB 3.0 and Hibernate will be highlighted, and additional comparison is provided in Hibernate 3.0 and EJB 3.0

Java Data Objects (JDO)

Java Data Objects, or JDO, differ more from Hibernate in terms of implementation than from the interface offered to developers. Specifically, JDO normally requires compile-time pre-processing of the Java byte-code in order to add persistence capability, whereas Hibernate performs similar tasks at runtime when the application is first started. There are also differences in the APIs used to query from the persistence source. In particular, JDO attempts to solve a larger issue of persistence, targeting data stores other than relational databases. The attempt to target a broader range of storage mechanisms leads to a different focus than the relational database-focused Hibernate, with a different set of query capabilities. It's unclear whether the goal of targeting nonrelational database persistence engines is worth the tradeoffs.

As of this writing, there has been some discussion of future versions of Hibernate and JDO moving closer together. Hibernate already supports three different interfaces (ODMG, HQL, and Criteria). It's entirely possible that future Hibernate releases may support a JDO style interface as well.

As of this writing, JDO implementations include:

TJDO, or TriActive JDO, is an open-source implementation of the JDO specification. It is explicitly designed to operate as Java persistence layer. In other words, the developer is expected to focus on Java development, with the database schema generated and managed by TJDO. It is not appropriate for situations with an existing schema. For more information, see http://tjdo.sourceforge.net/.

JPOX is another open-source JDO implementation. Unlike TJDO, more emphasis is placed on both schema-centric and Java-centric development. For more information, see http://www.jpox.org/.

JCredo provides a commercial implementation of JDO. A free edition is available for download from the Web site at http://www.jcredo.com/.

Apache OJB, available at http://db.apache.org/ojb/, provides both an ODMB and a JDO interface.

Castor is an open-source data-binding framework. While the implementation doesn't adhere precisely to the Sun JDO specification, it's similar enough that someone familiar with JDO can easily use Castor. For more information on Castor, see http://castor.exolab.org/.

How Does Sun Compare EJB and JDO?

Q. What is container managed persistence, and what are Java data objects?

A. EJB 2.0 CMP is the part of the J2EE component model that provides an object persistence service for EJB Containers. CMP's goal is to provide a standard mechanism for implementing persistent business components. CMP is not a general persistence facility for the Java platform. CMP provides distributed, transactional, secure access to persistent data, with a guaranteed portable interface. CMP is based on a functional set/get data-access model. It does not support transparent Java instance variable persistence.

A. JDO is an architecture that provides a standard way to transparently persist plain Java objects. It is designed to work in multiple tiers of an enterprise architecture, including J2SE, Web tier, and Application Servers. It does not itself provide distributed objects, distributed transactions, or security services, although it might be integrated with an EJB container that provides these services. CMP is for persisting distributed components built specifically to the entity bean component API. JDO is geared toward local, rich object models not tied to any particular API. Developers can choose between these technologies by evaluating their requirements (persistent components or persistent objects).

- From Sun's EJB 2.0 CMP and JDO FAQ, http://java.sun.com/products/jdo/JDOCMPFAQ.html


Other Commercial O/R Tools

There are a variety of commercial object/relational tools, some of which were in existence long before Hibernate, EJB, or JDO. The prices for these tools range from free to tens of thousands of dollars. Options in this arena include Oracle's TopLink (http://otn.oracle.com/products/ias/toplink/) and Software Tree's JDX (http://www.softwaretree.com/).

 

 

Hibernate 3.0

Gavin King, the creator of Hibernate, quite wisely avoids speaking of new features and functionality, but he does offer a preliminary preview of possible future directions for Hibernate 3 in his weblog at http://blog.hibernate.org/cgi-bin/blosxom.cgi/2004/04/02#three. In addition, a Hibernate roadmap has been posted at http://hibernate.bluemars.net/200.html.

To summarize the points made, the following are on the horizon as possible directions for Hibernate 3:

Virtualization: Session-level filtering of data. For example, you may wish to allow only data that belongs to a particular user to be viewed across an entire Web application. The virtualization feature will allow you to specify this at the session, instead of in your application code. This feature will probably be of special interest to Web application developers.

More Complex Relationships: As described in Chapter 7, Hibernate already offers support for a variety of complex relationships. Hibernate 3 will allow the use of a single class for multiple tables, table-per-concrete-class mappings, and the ability to use SQL to specify more complex discriminators.

Representation Independence: Allows a persistence model to be represented using entirely dynamic objects, instead of persistent objects. At some point, you may have realized that most JavaBeans could just as easily be represented by a single object with a single get/set property method (as described by the Apache BeanUtils, http://jakarta.apache.org/commons/beanutils/). This feature allows for a much broader suite of dynamic (i.e., runtime) discovery and manipulation of data.

JDK 1.5 Support: For more information on JDK 1.5, see http://java.sun.com/j2se/. Annotations allow XDoclet-style metadata to be embedded in a Java class file and easily accessed at runtime. Generics allow for more typesafe collections (i.e., less casting, more reliable compile-type checking).

Stored Procedures: This would be quite relevant if you are working on an application with legacy stored procedures.

Event-Driven Design: While the life-cycle methods described in Chapter 6 are reasonable, Hibernate lacks a full event model. Currently, the only way to instrument Hibernate to perform certain tasks is to download the source for Hibernate and add your own hooksand that is not the ideal situation.

New Parser Implementation: The grammar for HQL (as described in Chapter 8) is not fully documented and can be frustratingly vague in certain areas. Hibernate 3 should include a full grammar for HQL, as well as the ability to map new grammars on top of the existing implementation.

Declarative Session Management: Instead of session management constituting an explicit part of the application, Hibernate 3 will offer the ability to push this sort of detail into Hibernate and the session configuration.

Despite these changes, Hibernate 3 will not require JDK 1.5. As of this writing, Hibernate 3 is not even available as an alpha technology release.

June 08

Sendmail routing through Microsoft Active Directory

Sendmail routing through Microsoft Active Directory If you're reading this, you are probably running a Microsoft Exchange Server or probably currently already have sendmail relaying to an Exchange Server and want to improve your setup. Most sendmail to exchange setups will take mail and blindly relay the mail over. If yours is like this, you will know that you get email bounces that can go nowhere because most of the initial intentions of the emails were for spam and they would just send messages to users that they don't know even exist. A major problem with this is that it will hold up your sendmail queue and hinder your performance as it will try to send these emails just as much as the ones that are important and need to be sent out immediately. This article will show you how to use sendmail's ldap features to look into the Active Directory to see where the mail should go and have sendmail send it there. By having sendmail look into the Active Directory, it will know whether users exist and will stop immediately after the “RCPT TO” in the envelope if users don't exist, eliminating the useless, bounce emails that never get anywhere. This procedure is not fully supported by Sun support because of the amount of customization required. First off, you will need a version of sendmail that has ldap capabilities compiled into it. You can check this with: /usr/lib/sendmail -d0.11 < /dev/null Version 8.12.8+Sun Compiled with: DNSMAP LDAPMAP LOG MAP_REGEX MATCHGECOS MILTER MIME7TO8 When you see LDAPMAP, you know that it will work. Solaris 7-9 should all work. Patches are available for those that don't. The Microsoft Active Directory is a different ldap server than your typical ldap server, so you will want to browse the directory and learn more about how it's designed. You will need to find or create a user that can browse the Active Directory. For the sake of simplicity, this example will use the Administrator userid and his password to bind to the Active Directory server and find view its contents. For Solaris 8-9, if you have the SUNWlldap package installed, you can use the ldapsearch command located /usr/bin. Run something like: /usr/bin/ldapsearch -L -D "cn=Administrator, cn=Users, dc=domain, dc=com" \ -h domaincontroller.domain.com -b "dc=domain,dc=com" objectclass=* \ > /tmp/active_directory.ldif It will ask you for a password. You want to input the Windows Administrator's password there. You can open the /tmp/active_directory.ldif file and read it and you can find a lot of the information in the directory server. If you do not have the ldapsearch command, while logged in as Administrator on the Exchange server, you can achieve a similar result in Windows with ldifde -f c:\temp\export.ldif -v Upon knowing what's in the Active Directory, you can proceed to plug this data into your sendmail configuration. Because the Active Directory is a little different from your standard ldap server, some hacks are required to make sendmail work. You want to go into your /usr/lib/mail/hack directory. You can create it if the directory isn't there. In there, you want to create a file called AD_ldap_routing.m4 and inside of it have: --------------------------------------------------------------------------------- -------------------------- divert(0) VERSIONID(`$Id: ldap_routing.m4 with MSFT Active Directory HACKS,v 8.8 2001/06/27 21:46:31 gshapiro Exp $') divert(-1) # Check first two arguments. If they aren't set, may need to warn in proto.m4 ifelse(len(X`'_ARG1_), `1', `define(`_LDAP_ROUTING_WARN_', `yes')') ifelse(len(X`'_ARG2_), `1', `define(`_LDAP_ROUTING_WARN_', `yes')') # Check for third argument to indicate how to deal with non-existant # LDAP records ifelse(len(X`'_ARG3_), `1', `define(`_LDAP_ROUTING_', `_PASS_THROUGH_')', _ARG3_, `passthru', `define(`_LDAP_ROUTING_', `_PASS_THROUGH_')', `define(`_LDAP_ROUTING_', `_MUST_EXIST_')') # Check for fouth argument to indicate how to deal with +detail info ifelse(len(X`'_ARG4_), `1', `', _ARG4_, `strip', `define(`_LDAP_ROUTE_DETAIL_', `_STRIP_')', _ARG4_, `preserve', `define(`_LDAP_ROUTE_DETAIL_', `_PRESERVE_')') LOCAL_CONFIG # LDAP routing maps Kldapmh ifelse(len(X`'_ARG1_), `1', `ldap -1 -v msExchHomeServerName,msExchExpansionServerName -k (|(mail=%0)(proxyaddresses=smtp:%))', `_ARG1_') Kldapmra ifelse(len(X`'_ARG2_), `1', `ldap -1 -v targetAddress -k (|(mail=%0)(proxyaddresses=smtp:%0))', `_ARG2_') --------------------------------------------------------------------------------- ---------------------------- You will need to replace the with real tabs. The next step is to make the modifications to your .mc file. The first feature we should add is a mailertable to tell sendmail where to send mail with different ldapsearch results. So we add the line: FEATURE(`mailertable') To add the ldap features into sendmail. Add the lines (of course, you put in your domains): HACK(`AD_ldap_routing') LDAPROUTE_DOMAIN(`domain.com')dnl # what domain to do ldap lookups for. LDAPROUTE_DOMAIN(`secondarydomain.com')dnl # alternate domain to do ldap lookups for. You then need to specify your Active Directory settings (this all fits on one line). You will also need to create the file /etc/mail/ldap.passwd. (We will do this later) define(`confLDAP_DEFAULT_SPEC',`-h domaincontroller.domain.com -M simple -d "cn=Administrator, cn=Users, dc=domain, dc=com" -P /etc/mail/ldap.passwd -p 389 -b "dc=domain, dc=com"') We will now have to add some custom rulesets. You will again need to change the to real tabs. There's also one line you need to change here. R<> $>LDAPMailertable $2 Make it match your organzation. You can find this by looking at your active_directory.ldif file and seeing the msExchHomeServerName attribute. Every user entry should have something like: msExchHomeServerName: /o=Domain/ou=First Administrative Group/cn=Configuration/cn=Servers/cn=domaincontroller With that, you just strip off the last cn= and make spaces in between. --------------------------------------------------------------------------------- --------------------- LOCAL_NET_CONFIG R$* < @ $=m . > $*$#esmtp $@ $2 $: $1 < @ $2 . > $3internal addr delivered to host R$* < @ $+ . $=m . > $*$#esmtp $@ $2 . $3 $: $1 < @ $2 .$3 . > $4internal w/host # Begin custom LDAP rule set. # the following lines are essentually copied from the proto.m4 file. They are entered here to maintain the proper, # original flow control but process the Active Directory response properly. # pass names that still have a host to a smarthost (if defined) R$* < @ $* > $*$: $>MailerToTriple < $S > $1 < @ $2 > $3glue on smarthost name # deal with other remote names R$* < @$* > $*$#esmtp $@ $2 $: $1 < @ $2 > $3user@host.domain # handle locally delivered names R$=L$#local $: @ $1special local names R$+$#local $: $1regular local names SLDAPExpand #do the LDAP lookup for the Exchange Mail Host R$: # if mailRoutingAddress (targetAddress) and local or non-existant mailHost, # return the new mailRoutingAddress R $@ $>Parse0 $>canonify $1 R <> $@ $>Parse0 $>canonify $1 # fix hostname in Mailertable, relay from there R $>LDAPMailertable $>canonify $1 # if no mailRoutingAddress and local mailHost, return original address R<> $@ $2 # if no mailRoutingAddress and non-local mailHost, # relay to mailHost (Exchange Server) with original address # "de-AD" response at same time # You'll need to do the query manually the find the proper stuff to pull out R<> $>LDAPMailertable $2 # if still no mailRoutingAddress and no mailHost, # try @domain R<> <> $@ $>LDAPExpand # if no mailRoutingAddress and no mailHost and this was a domain attempt, # return the original address R<> <> $@ $1 # End of custom LDAPExpand rule set --------------------------------------------------------------------------------- --------------------- You now want to create your cf file. /usr/ccs/bin/m4 ../m4/cf.m4 file.mc > file.cf Now that we're done with the cf file, we need to supply the other files to the configuration. Create the ldap.passwd file: echo "activedirectorypassword" > /etc/mail/ldap.passwd Create the mailertable to tell sendmail where to send the mail. When we stripped the last cn= off of the msExchHomeServerName, we will take that and put it here. So my /etc/mail/mailertable will look like: cn=domaincontroller esmtp:exchangeserver.domain.com After you create this file, you will need to put it in the database for sendmail to read it. Do this by running the command: makemap -v hash /etc/mail/mailertable < /etc/mail/mailertable You will also need to tell sendmail that you take mail for the domain as well, so you want to put your domain in /etc/mail/local-host-names. echo "domain.com" > /etc/mail/local-host-names Now we will need to restart sendmail and test it. Run a command like this for a user in the Active Directory: /usr/lib/sendmail -bv alton@domain.com You should see: alton@domain.com... deliverable: mailer esmtp, host domaincontroller.domain.com, user alton@domain.com If you run the same command on a user that's not in the Active Directory, you should get: /usr/lib/sendmail -bv other@domaincontroller.domain.com other@domain.com... User unknown Once you've got this, you're all set! --------------------------------------------------------------------------------- ---------------------------- Some ideas on troubleshooting: If you see /usr/sbin/sendmail -bv alton@domain.com alton@domain.com... deliverable: mailer relay, host cn=exchangeserver, user alton@domain.com You probably forgot the mailertable. The mailertable translates the cn=host to the actual host and tells it which protocol to use to send the mail. In our case, we use esmtp. If you see something like this: /usr/sbin/sendmail -bv alton@domain.com alton@domain.com... deliverable: mailer esmtp, host domain.com., user >/o=domain/ou=First.Administrative.Group/cn=Configuration/cn=Servers/cn=exchange server.alton@domain.com.alton@domain.com< You have the wrong data in the area where it says: # relay to mailHost (Exchange Server) with original address # "de-AD" response at same time in the sendmail.mc file.

J2EE patterns

J2EE Patterns

We used the tiered approach to divide the J2EE patterns according to functionality, and our pattern catalog follows this approach. The presentation tier patterns contain the patterns related to servlets and JSP technology. The business tier patterns contain the patterns related to the EJB technology. The integration tier patterns contain the patterns related to JMS and JDBC.

Presentation Tier Patterns

Table 5-1 lists the presentation tier patterns, along with a brief description of each pattern.

Table 5-1. Presentation Tier Patterns

Pattern Name

Synopsis

Intercepting Filter (144)

Facilitates preprocessing and post-processing of a request.

Front Controller (166)

Provides a centralized controller for managing the handling of a request.

Context Object (181)

Encapsulates state in a protocol-independent way to be shared throughout your application.

Application Controller (205)

Centralizes and modularizes action and view management.

View Helper (240)

Encapsulates logic that is not related to presentation formatting into Helper components.

Composite View (262)

Creates an aggregate View from atomic subcomponents.

Service to Worker (276)

Combines a Dispatcher component with the Front Controller (166) and View Helper (240) patterns.

Dispatcher View (288)

Combines a Dispatcher component with the Front Controller (166) and View Helper (240) patterns, deferring many activities to View processing.

Business Tier Patterns

Table 5-2 lists the business tier patterns, along with a brief synopsis of each pattern.

Table 5-2. Business Tier Patterns

Pattern Name

Synopsis

Business Delegate (302)

Encapsulates access to a business service.

Service Locator (315)

Encapsulates service and component lookups.

Session Façade (341)

Encapsulates business-tier components and exposes a coarse-grained service to remote clients.

Application Service (357)

Centralizes and aggregates behavior to provide a uniform service layer.

Business Object (374)

Separates business data and logic using an object model.

Composite Entity (391)

Implements persistent Business Objects (374) using local entity beans and POJOs.

Transfer Object (415)

Carries data across a tier.

Transfer Object Assembler (433)

Assembles a composite transfer object from multiple data sources.

Value List Handler (444)

Handles the search, caches the results, and provide the ability to traverse and select items from the results.

Integration Tier Patterns

Table 5-3 lists the integration tier patterns and a brief description of each pattern.

Table 5-3. Integration Tier Patterns

Pattern Name

Synopsis

Data Access Object (462)

Abstracts and encapsulates access to persistent store.

Service Activator (496)

Receives messages and invokes processing asynchronously.

Domain Store (516)

Provides a transparent persistence mechanism for business objects.

Web Service Broker (557)

Exposes one or more services using XML and web protocols

    June 07

    Common tuning practices for EJBs - Key Points

     

    Common tuning practices for EJBs

    1. Use Local interfaces that are available in EJB2.0 if you deploy both EJB Client and EJB in the same EJB Server.

    2. Use Vendor specific pass-by-reference implementation to make EJB1.1 remote EJBs as Local EJBs if you deploy both EJB Client and EJB in the same EJB Server.

    3. Wrap entity beans with session beans to reduce network calls and to promote declarative transactions. Optionally, make entity beans as local beans where appropriate.

    4. Make coarse grained session and entity beans to reduce network calls.

    5. Control serialization by modifying unnecessary data variables with  'transient' key word to avoid unnecessary data transfer over network.

    6. Cache EJBHome references to avoid JNDI lookup overhead.

    7. Avoid transaction overhead for non-transactional methods of session beans by declaring 'NotSupported' or 'Never' transaction attributes that avoid further propagation of transactions.

    8. Set proper transaction age(time-out) to avoid large transaction.

    9. Use clustering for scalability.

    10. Tune thread count for EJB Server to increase EJB Server capacity.

    11. Choose servlet's HttpSession object rather than Stateful session bean to maintain client state if you don't require component architecture and services of Stateful session bean.

    12. Choose best EJB Server by testing with ECperf tool kit.

    13. Choose normal java object over EJB if you don't want built-in services such as RMI/IIOP, transactions, security, persistence, resource pooling, thread safe, client state etc..

    Stateless session beans

    1. Tune the Stateless session beans pool size to avoid overhead of creation and destruction of beans.

    2. Use setSessionContext() or ejbCreate() method to cache bean specific resources.

    3. Release acquired resources in ejbRemove() method

    Stateful session beans

    1. Tune Stateful session beans cache size to avoid overhead of activation and passivation process.

    2. Set optimal Stateful session bean age(time-out) to avoid resource congestion.

    3. Use 'transient' key word for unnecessary variables of Stateful session bean to avoid serialization overhead.

    4. Remove Stateful session beans explicitly from client using remove() method.

    Entity beans

    1. Tune the entity beans pool size to avoid overhead of creation and destruction of beans.

    2. Tune the entity beans cache size to avoid overhead of activation, passivation and database calls.

    3. Use setEntityContext() method to cache bean specific resources.

    4. Release acquired resources in unSetEntityContext() method

    5. Use Lazy loading to avoid unnecessary pre-loading of child data.

    6. Choose optimal transaction isolation level to avoid blocking of other transactional clients.

    7. Use proper locking strategy.

    8. Make read-only entity beans for read only operations.

    9. Use dirty flag to avoid unchanged buffer data updation.

    10. Commit the data after the transaction completes to reduce database calls in between transaction.

    11. Do bulk updates to reduce database calls.

    12. Use CMP rather than BMP to utilize built-in performance optimization facilities of CMP.

    13. Use ejbHome() methods for global operations.

    14. Tune connection pool size to reduce overhead of creation and destruction of database connections.

    15. Use JDBC tuning techniques in BMP.

    16. Use direct JDBC rather than using entity beans when dealing with huge data such as searching a large database.

    17. Use business logic that is specific to entity bean data.

    Message driven beans

    1. Tune the Message driven beans pool size to promote concurrent processing of messages.

    2. Use setMesssageDrivenContext() or ejbCreate() method to cache bean specific resources.

    3. Release acquired resources in ejbRemove() method.

    4. Use JMS tuning techniques in Message driven beans.

    Tuning Entity beans

    Tuning Entity beans

    The common tuning practices that we discussed above are applicable for Entity beans also. Here we discuss specific practices for Entity beans. In order to get a clear picture, we will initially  discuss Entity bean life cycle.  Here we discuss the tuning practices for both CMP (Container managed persistence) and BMP (Bean managed persistence). Let us start with entity bean life cycle.

    Entity bean life cycle

    The life cycle of Entity beans is a combination of Stateless and Stateful bean life cycles. There is slight difference between Container managed persistence (CMP) and Bean managed persistence (BMP) entity bean's life cycle that is negligible. So here we will discuss a generalized life cycle that applies to both.

    The following figure illustrates the life cycle of Entity beans.

    Figure7: Entity session bean life cycle

    Here you see both instance pool and instance cache. instance pool maintains entity beans without state data and instance cache maintains entity beans with state data.

    You can control life cycle in Entity beans by mentioning instance pool size and instance cache size in vendor specific deployment descriptor. For example weblogic's weblogic-ejb-jar.xml has element for instance pool size,

    <pool>

            <max-beans-in-free-pool>100</max-beans-in-free-pool>

            <initial-beans-in-free-pool>50</initial-beans-in-free-pool>

    </pool>

    and instance cache size

    <entity-cache>

            <max-beans-in-cache>100</max-beans-in-cache>

    </entity-cache>

    and in JBoss, jboss.xml has an element

    <instance-pool> to mention pool size.

    and for instance cache size

    <instance-cache>

    <container-cache-conf>

            <cache-policy>

                    <cache-policy-conf>   

                              <min-capacity>5</min-capacity>       

                            <max-capacity>10</max-capacity>   

                 

                    </cache-policy-conf>   

            </cache-policy>

    </container-cache-conf>

    </instance-cache>

     If you mention 50 beans as initial beans and 100 beans as maximum beans for instance pool, 50 (min) and 100(max) for instance cache, life cycle starts when the server starts up.

    When the server starts up, First, the EJB Container/Server creates 50 beans using Class.newInstance() method and puts them in the pool and it calls setEntityContext() method on each bean. The Container can remove beans from the pool depending on clients accesses and idle time of beans in the pool. When it removes the bean from the pool it calls unSetEntityContext() method on the bean. 

    Next, When the client calls the create() method, the Container calls corresponding ejbCreate() method on one of the beans in the instance pool and creates a row in the database and populates the values to the variables and puts it in the instance cache after returning primary key. At this stage an EJBObject is assigned to the client that communicates to the bean in the instance cache. Next, the Container calls ejbPostCreate() method. At this stage, the bean is moved from pool to cache and is ready to serve clients business methods.

    Next, When the client calls the business method, the Container calls ejbLoad() that updates the beans state, executes the business method, and calls ejbStore() method to store the data in the database. If the concurrent active clients are more than cache size then the container passivates a bean and calls ejbStore(), ejbPassivate() methods and puts it back in the instance pool. If the idle client calls again after some time, container calls ejbLoad() to get latest data, and calls ejbActivate() method and puts it in the instance cache.

    Next, If the client calls remove() method, the Container calls ejbRemove() method that removes the data from the database and puts the bean back in the instance pool from instance cache.

    With this discussion, we understand that

    1. Client controls life cycle of a bean that involves creation of data in the database thus moving the bean from pool to the cache and removal of data from the database thus moving the bean from cache to the pool.

    2. Container controls the life cycle in the pool and cache and also activation and passivation process in the cache.

    3. Both client and container control ejbLoad() and ejbStore() methods depending upon client's method calls and Container activation and passivation process.

    Finally the overall life cycle depends upon clients concurrent operations, instance pool size and instance cache size.

    Now let us discuss how we can tune Entity beans.

    Tune Entity beans instance pool size

    As per Entity bean life cycle discussion, we understand that we can control creation and destruction of beans by describing pool size(min and max) in vendor specific deployment descriptor (or other vendor specific manner). If this size is less (if your default size is less or you configure a smaller size) then the Container has to put the clients in the queue when the number of concurrent clients accessing ( create/finder/home methods) are more than the max pool size. And also instance cache depends up on instance pool because the instance cache needs to get beans from the instance pool. So if the pool size is less, It degrades the performance and clients take more time to execute. For best performance, give maximum beans in pool as equal to number of maximum concurrent client accesses (create/finder/home methods), so that it reduces creation and destruction of beans.

    You can configure your pool size in vendor specific deployment descriptor ( or other vendor specific manner). In the above Entity bean life cycle section, We discussed how to configure this pool size in Weblogic and JBoss servers.

    Tune Entity beans instance cache size

    As per Entity bean life cycle discussion, we understand that we can control activation and passivation indirectly by describing instance cache size in vendor specific deployment descriptor file (or other vendor specific manner). Look at Entity bean life cycle section for configuring instance cache size in Weblogic and JBoss servers.

    Activation and passivation are expensive. For every activation the Container calls ejbLoad() to get latest data from the database and calls ejbActivate() method. For every passivation the Container calls ejbStore() to store data in the database and calls ejbPassivate() method. ejbLoad() and ejbStore() methods communicate with the database to synchronize the latest data. If the concurrent active clients (when the client calls business methods) are more than instance cache size then activation and passivation occur often thus effecting performance. So in order to increase performance, give optimal cache size. Cache size must be equal to concurrent active clients accessing the bean.

    Note: The instance cache size and pool size in entity beans are larger than session beans. The beans in the pool and cache should accommodate the entity beans requirements like finder methods that return large number of records and populate the data in the beans. So be careful when you configure entity bean pool size and cache size. If you are not sure about what the exact parameters are then use default pool size and cache size.

    Use setEntityContext() method as cache

    setEntityContext() is called only once in a bean's life time. Because Entity beans in the pool are reused by number of other clients, you can cache any bean specific resources like Entity home references and DataSource references in this method. You need to declare those resources as instance variables and acquire them in this method. It is similar to the technique that we already discussed in Use setSessionContext() as cache. These resources will be specific to a bean but not available globally. For global reuse, it is better to use the technique that we discussed in  Cache EJBHome object references. You can use this technique to acquire other resources also. Remember that you should not acquire physical resources like database connections in these methods if the concurrent clients are more and pool size is more, it is better to acquire such resources in each method and release them in that method only. Use setEntityContext() method to cache bean specific resources that are needed by other clients as well.

    Release resources in unSetEntityContext() method

    The Container calls unSetEntityContext() method just before removing a bean from the pool. So whatever resources that were acquired (as we discussed above) need to be released in this method. 

    Use Lazy loading

    Whenever you implement parent child relationships 1:1 (one to one), 1:M (one to many) and M:M (many to many) in your Entity beans, you need to be careful about when you are loading child ( sub relationship) data.

    For example, in BMP, you would write a 1:M (OrderBean:LineItem entity beans) relationship like this

    public class OrderBean implements EntityBean {

            private long orderId;

            private String orderName;

            private long lineItemId;    // FK to the child table LineItems table   

            private Collection lineItems;    // child data from LineItems table

        public void ejbLoad() {

                // step1: select orderId, orderName and lineItemId from Order table

                /* step2: get lineItems by looking up LineItem entity bean

                           : look up LineItem home reference through JNDI

                           lineItems = lineItemHome.findLineItems(lineItemId);

             */

        }

        public Collection getLineItems(){

                return lineItems;

        }

    Here you are getting data for both parent and child (OrderBean and LineItem) in one call in ejbLoad() method. This is called as aggressive/eager loading. Here you are getting data from the database on client's every business method request or when transaction ends. But client may often be interested in orderId and orderName only but not LineItems. For example, if you use finder method to get orders, you might get 100 orders and 1000 lineItems. You get 1000 lineItems records unnecessarily even though the client didn't want lineItems. Remember that ejbLoad() is called even when the Container wants to activate a bean, this is an extra overhead.

    You can solve this problem using Lazy loading. In Lazy loading, you load the child data as and when required. The above example can  be rewritten like this :

    public class OrderBean implements EntityBean {

            private long orderId;

            private String orderName;

            private long lineItemId;    // FK to the child table LineItems table   

            private Collection lineItems;    // child data from LineItems table

        public void ejbLoad() {

                // step1: select orderId, orderName and lineItemId from Order table

        }

        public Collection getLineItems(){

              /* step2: get lineItems by looking up LineItem entity bean

                           : look up LineItem home reference through JNDI

                           lineItems = lineItemHome.findLineItems(lineItemId);

             */

                return lineItems;

        }

    Here you load the data as and when client calls getLineItems() but not when it calls other business methods. So Lazy loading is best to improve performance and use it when you implement relationships in Entity beans.

    Choose optimal transaction isolation level

    Isolation levels represent how a database maintains data integrity against the problems like dirty reads, phantom reads and non-repeatable reads which can occur due to concurrent transactions. You can avoid these problems by describing following isolation levels in vendor's deployment descriptor file(or other vendor specific manner)

            TRANSACTION_READ_UNCOMMITED

            TRANSACTION_READ_COMMITED

            TRANSACTION_REPEATABLE_READ

            TRANSACTION_SERIALIZABLE

    The top most is least isolation level and bottom most is strict isolation level. Databases use read and write locks depending on above isolation levels to control transactions. Let us first discuss the problems related to concurrent transactions to the database and then the remedy to these problems.

    Problems due to concurrent transactions

    The following table describes isolation level against the problem that it prevents :

     

    Transaction Level

     

                              Permitted Phenomena

     

    Performance impact       Dirty reads

     

     Non  Repeatable reads Phantom reads   TRANSACTION_READ_UNCOMMITED YES YES YES FASTEST TRANSACTION_READ_COMMITED NO YES YES FAST TRANSACTION_REPEATABLE_READ NO NO YES MEDIUM TRANSACTION_SERIALIZABLE NO NO NO SLOW

    YES means the transaction level does not prevent the problem

    NO means the transaction level prevents the problem

    By setting isolation levels, you are having an impact on the performance as mentioned in the above table. Databases use read and write locks to control above isolation levels. Let us have a look at each of these problems, and then look at the impact on the performance.

    Dirty read problem :

    The following figure illustrates Dirty read problem  :

    Step 1:     Database row has PRODUCT = A001 and PRICE = 10

    Step 2:    Connection1 starts  Transaction1 (T1) .

    Step 3:    Connection2 starts  Transaction2 (T2) .

    Step 4:    T1 updates PRICE =20 for PRODUCT = A001

    Step 5:    Database has now PRICE = 20 for PRODUCT = A001

    Step 6:    T2 reads PRICE = 20 for PRODUCT = A001

    Step 7:    T2 commits transaction

    Step 8:    T1 rollbacks the transaction because of some problem

    The problem is that T2 gets wrong PRICE=20 for PRODUCT = A001 instead of 10 because of uncommitted read. Obviously it is very dangerous in critical transactions if you read inconsistent data. If you  are sure about not accessing data concurrently  then you can allow this problem by setting TRANSACTION_READ_UNCOMMITED or TRANSACTION_NONE elseTRANSACTION_READ_COMMITED to avoid this problem.

     

    Unrepeatable read problem :

    The following figure illustrates Unrepeatable read problem  :

    Step 1:     Database row has PRODUCT = A001 and PRICE = 10

    Step 2:    Connection1 starts  Transaction1 (T1) .

    Step 3:    Connection2 starts  Transaction2 (T2) .

    Step 4:    T1 reads PRICE =10 for PRODUCT = A001

    Step 5:    T2 updates PRICE = 20 for PRODUCT = A001

    Step 6:    T2 commits transaction

    Step 7:    Database row has PRODUCT = A001 and PRICE = 20

    Step 8:    T1 reads PRICE = 20 for PRODUCT = A001

    Step 9:    T1 commits transaction

    Here the problem is that Transaction1 reads 10 first time and reads 20 second time but it is supposed to be 10 always whenever it reads a record in that transaction. You can control this problem by setting isolation level as TRANSACTION_REPEATABLE_READ.

    Phantom read problem :

    The following figure illustrates Phantom read problem  :

     

    Step 1:     Database has a row PRODUCT = A001 and COMPANY_ID = 10

    Step 2:    Connection1 starts  Transaction1 (T1) .

    Step 3:    Connection2 starts  Transaction2 (T2) .

    Step 4:    T1 selects a row with a condition SELECT PRODUCT WHERE COMPANY_ID = 10

    Step 5:    T2 inserts a row with a condition INSERT PRODUCT=A002  WHERE

                       COMPANY_ID= 10

    Step 6:    T2 commits transaction

    Step 7:    Database has 2 rows with that condition

    Step 8:    T1 select again with a condition SELECT PRODUCT WHERE COMPANY_ID=10            

                    and gets 2 rows instead of 1 row

    Step 9:    T1 commits transaction

    Here the problem is that T1 gets 2 rows instead of 1 row up on selecting the same condition second time. You can control this problem by setting isolation level as TRANSACTION_SERIALIZABLE

    Choosing a right isolation level for your program:

    Choosing a right isolation level for your program depends upon your application's requirement. In a single application itself the requirement generally changes, suppose if you write a program for searching a product catalog from your database then you can choose TRANSACTION_READ_ UNCOMMITED because you need not worry about the isolation problems , some other program can insert records at the same time, you don't have to bother much about that insertion. Obviously this improves performance significantly.

    If you write a critical program like bank or stocks analysis program where you want to control all of the isolation problems, you can choose TRANSACTION_SERIALIZABLE for maximum safety. Here it is the tradeoff between the safety and performance.

    Other two isolation levels need good understanding of your requirement. If your application needs only committed records, then TRANSACTION_READ_COMMITED isolation is the good choice. If your application needs to read a row exclusively till you  finish your work, then TRANSACTION_REPEATABLE_READ is the best choice.

    Note: Be aware of your database server's support for these isolation levels. Database servers may not support all of these isolation levels. Oracle server supports only two isolation levels, TRANSACTION_READ_COMMITED and TRANSACTION_SERIALIZABLE isolation level, default isolation level is TRANSACTION_READ_COMMITED.

    Use proper locking strategy

    We discussed above how a database can lock data depending on isolation level. The locking that  happens at database level, is called as database locking strategy. Other than that, Your EJBServer/Container can support different locking strategies. Some EJB vendors such as Weblogic supports exclusive locking strategy that locks Entity beans at application server itself rather than at the database. Exclusive locking blocks other Entity beans till locked Entity bean completes it's transaction. This locking does not allow other beans to even read the data , it has an impact on performance. Your application server may have default locking strategy of either database locking or exclusive locking, it may have even other locking strategies. You need to configure your vendor's deployment descriptor file so that you can override default locking strategy depending on your application's requirement to improve performance.

    Make read-only Entity beans

    In your EJB application, your entity beans might be always getting data from the database but not updating data. But by default, your application server would read and write data using ejbLoad() and ejbStore() methods for every business method call or end of transaction. Why would you update database using ejbStore() method while your entity bean performs read only transactions? this effects performance by calling unnecessary ejbStore() methods. In this situation, if your EJBServer/Container supports configuring for read only or read-write entity beans, it is better to configure as read only beans in vendor's deployment descriptor file to improve performance. If you configure your entity bean as read only then there will be no updates ( no ejbStore() calls) to the database, so be careful when you configure this property. Some vendors support read-mostly property where you can configure when to read from database, you can also configure this feature if you need to reduce frequency of ejbLoad() calls. Look at your vendor's  EJB server/container documentation on how to configure read only property.

    Use dirty flag to avoid unchanged buffer data updation

    EJB Container calls ejbStore() method when the business method execution completes or when the transaction completes irrespective of change in the bean's data. The entity bean's data may not change every time when the client calls the business method. So there will be lot of updates ( calls to ejbStore() ) to the database even though it doesn't require, thus degrading performance. To avoid this problem, you can configure dirty flag property in vendor specific deployment descriptor file for CMP1.1, for example is-modified-method-name in weblogic server's weblogic-ejb-jar.xml file. For EJB2.0 CMP, it does not require to configure because EJB2.0 CMP Container supports this feature implicitly. For BMP, you need to write this method in bean's class and call this method wherever necessary. This technique reduces calls to the database unless the bean's data changes, thus improving performance.

    Commit the data after transaction

    By default, Your EJB Container either commits the data after every method call or after completing the whole transaction. For example, in one transaction, if you call four methods of two entity beans from one session bean method, then the Container can either commit the data after each of the entity beans method's execution that calls ejbStore() method four times or it commits the data only once after execution of session bean method with four entity bean methods that completes whole transaction. Obviously if the transaction commits after it finishes completely, then it improves performance significantly. But other clients cannot see the data till it completes transaction. If your EJB Container/Server supports this feature, you can configure this feature in vendor's deployment descriptor or other vendor specific means. For example, weblogic server's weblogic-ejb-jar.xml has an element 'delay-updates-until-end-of-tx', that updates the database after completion of transaction. So commit the data after transaction by configuring vendor's file if you don't need other clients to read transactional data in between.

    Do bulk updates

    If you use relationships  (1:1, 1:M, M:M) in CMP entity beans and want to update both parent and child data (bulk data), it is  better to update the both parent and child data at the same time using vendor specific features. For example, weblogic supports this feature as field groups. Bulk updates reduces number of calls to the database and improves performance.

    Use CMP instead of BMP

    Before introduction of EJB2.0 specification often developers used BMP rather than CMP because the previous EJB spec does not support enough important features like relationships. But EJB2.0 spec for CMP has good relationship support as well as performance improvements.

    One of the CMP performance improvement technique in EJB2.0 is that the Container can monitor bean's data (in-memory buffer) change and if any changes happens in that data then only Container will update the database. Because of this monitoring capability, CMP gives better performance than BMP. And another technique is when you call finder method in BMP, it initially retrieves primary key with first call to the database and then instance data by placing a second call to the database. It makes two calls to the database. But CMP gets the data with single call to the database for the finder methods. Thus CMP  gives better performance than BMP because Container has good hold on CMP.

    Use ejbHome() methods for global operations  

    EJB2.0 specification introduced ejbHome() methods in Entity beans. You can use these methods to perform global operations ( for example, getting total number of persons) that do not relate to any specific entity bean instance data. When you call home methods from client, the Container calls the ejbHome() method on the bean that is in the instance pool before assigning any EJBObject to the client. This improves performance because the bean does not have state maintenance.

    So use ejbHome() methods for global operations that do not have state (instance variables data) dependency.

    Use connection pool

    Creating a connection to the database server is expensive. It is even more expensive if the server is located on another machine. Connection pool contains a number of open database connections, and has open connections between minimum and maximum number that you specify in vendor specific manner. The pool expands and shrinks between minimum and maximum size depending on incremental capacity. You need to give minimum, maximum and incremental sizes as properties to the pool in order to maintain that functionality. You get the connection from the pool instead of getting it directly from the database. For example, if you give properties like min, max and incremental sizes as 3, 10 and 1 then pool is created with size 3 initially and if it reaches its capacity 3 and if a client requests a connection concurrently, it increments its capacity by 1 till it reaches 10 and later on it puts all it's clients in a queue. You need to configure connection pool size in vendor specific manner and you need to to take care of properties like min, max and increment sizes. The maximum number of connections to be opened depend on your application's  requirement and the maximum number of open connections your database can support.

    In EJB deployment descriptor files, you need to configure DataSource reference that uses connection pool. Your EJB application improves performance significantly depending on connection pool size. So configure optimal connection pool to reduce expensive creation and destruction of database connections thus improving performance significantly.

    Use JDBC tuning techniques

    When you write BMP, you need to write JDBC code on your own. JDBC has lot of techniques to improve performance. There is a separate section for JDBC in this site. Those techniques are   

    Use these techniques in BMP to boost your BMP performance.

    Use direct JDBC when dealing with huge data

    Generally developers prefer JDBC over entity beans due to  performance considerations. Entity bean is a component that has an overhead about which we discussed in Choosing between EJB vs. non-EJB. Obviously Entity beans have advantages because of their component architecture.  To get EJB architecture to some extent you can wrap JDBC with session beans. When it comes to choosing between entity beans versus JDBC calls, you can decide depending on quantity of data. For example, if you search data that retrieves 50000 records, JDBC is a better choice when compared to entity beans. Entity beans are not a problem with small data and you can even increase performance by the techniques which we discussed. So use JDBC with session beans when you deal with huge data to improve performance.

    Use business logic in Entity beans

    You should consider an entity bean not only as a data access object but also as a business object. Business logic depends purely on application business requirement or on data. If you write business methods that depend on data in entity bean, it reduces network calls on remote entity beans by reducing round trips for getting data. This works well when your entity beans are remote EJBs. So put business logic that depends on data, in remote entity beans there by reducing network calls.

    Tuning Message driven beans

    The session beans and entity beans can act as JMS producers using JMS API but can only consume messages synchronously using MessageConsumer.receive() method. The reason for synchronous consumption of messages is that session and entity beans implement request-reply process synchronously but not asynchronously, that is why we have Message driven beans in EJB2.0. Message driven beans consume messages asynchronously from JMS Server.

    We already discussed Common tuning practices practices in EJB in the above sections. Some of those practices such as Cache EJBHome object references, Use Clustering for scalability, Tune thread count, are applicable for Message driven beans also. Here we discuss about specific practices for Message driven beans. In order to get clear understanding of following tuning practices, we will discuss Message driven bean life cycle first.

    Message driven bean life cycle

    The life cycle of Message driven bean is analogous to the Stateless session bean because it also need not maintain client state. The main difference between them is that Stateless beans have business methods that are invoked by clients where as Message driven beans have onMessage() method of MessageListener interface that has business logic. The Message driven beans simply connect to the JMS server, consume messages from it and process those messages. A Message driven bean does not have a remote or home interface because it is not an RMI/IIOP component rather it uses JMS protocol to connect to the JMS server.

    The following figure illustrates the life cycle of Message driven bean.

    You can control the number of message driven beans by mentioning instance pool size in vendor specific deployment descriptor. This controls when the beans are created, removed and call back methods are called. For example in weblogic's weblogic-ejb-jar.xml has element for instance pool size, that is

    <pool>

            <max-beans-in-free-pool>100</max-beans-in-free-pool>

            <initial-beans-in-free-pool>50</initial-beans-in-free-pool>

    </pool>

     Here you can specify initial beans and maximum beans in the pool. If you mention for example 50 beans in initial beans and 100 for maximum beans in the pool, the life cycle starts when the server starts up.

    When the server starts up, the EJB Container/Server creates 50 beans using Class.newInstance() method and puts it in the pool and it calls the following call back methods of the bean.

            setMessageDrivenContext(ctx) and

            ejbCreate() methods

    those 50 beans are ready for consuming and processing 50 concurrent messages. If the concurrent messages are more than 50 then the Container creates more beans and calls the above methods till it reaches 100 beans (maximum beans in the pool). So at any time the Container can only have a maximum of 100 beans to consume messages concurrently. What will happen if the concurrent messages are more than 100?  well, the container has to wait till beans are available in the pool.

    When the message arrives, the container passes that message to onMessage(Message msg) method of one of the beans in the pool so that method can process business logic.

    The Container removes the beans from the pool if the number of messages arriving are not many.  How the Container removes the beans are depends upon it's specific algorithms. At this time Container calls ejbRemove() method of the bean and destroys the bean from the pool.

    The creation and destruction of beans occurs depending on instance pool size and consumption (or arrival of messages to the Destination) of  messages.

    With this discussion, we understand the importance of pool size and when the call back methods are executed in Message driven beans. Now let us discuss how we can tune Message driven beans.

    Tune Message driven beans instance pool size

    The creation and destruction of beans is expensive. To reduce this cost, the EJB Container/Server creates pool of beans (that is vendor specific), you need to give optimal pool size for better performance. As we discussed above, you can give this pool size ( initial beans and maximum beans) for example in weblogic's weblogic-ejb-jar.xml has an element <pool>. See your vendor documentation for more information.

    The maximum number of beans in the pool effects performance. If this is less, then the Container has to put the messages in the wait mode in the JMS server when the number of messages arriving are more than the max pool size. It degrades the performance and takes more time to execute. For best performance, give maximum beans in the pool as equal to expected number of maximum concurrent messages.

    Use setMessageDrivenContext() or ejbCreate() method as cache

    In Message driven bean life cycle, the container invokes the setMessageDrivenContext() and ejbCreate() methods only once in it's life time when it creates the bean instance first time and puts it in the pool  and later it will be used for the processing other messages till it is removed by the Container,You can use these methods to acquire resources like ConnectionFactory references, Destination references, home objects references of other session or entity beans or DataSource references and assign to the instance variables. Once you acquire these resources in these methods you need not create resources for processing other messages because those resources are already acquired and available for other message processes. Obviously these resources will be specific to a bean but will not be available globally. For global reuse, it is better to use the technique that we already discussed in Cache EJBHome object references, you can use this technique to acquire other resources also. Remember that you should not acquire physical resources like database connections in these methods if the concurrent arrival of messages are more and pool size is more, it is better to acquire those type of resources in onMessage() method and remove in the same method. Use setMessageDrivenContext() and ejbCreate() methods to cache bean specific resources that are needed for other clients.

    Remove resources in ejbRemove()

    In Message driven beans, the Container calls ejbRemove() method just before removing a bean from the pool like Stateless session beans. So whatever resources you acquired in your bean (as discussed above)  need to be released in this method. 

    Use JMS tuning techniques

    We have separate section for JMS, See Best practices to improve performance in JMS. Those practices are meant for both JMS producers and JMS consumers. You can specifically look at Consumer techniques (Message driven bean act as consumer) to improve overall performance of Message driven beans. See   

    Use these techniques to boost your Message driven bean's performance.

    Best Practices to improve performance in Session EJB

    Choosing between HttpSession and Stateful session bean

    Both Servlet's HttpSession object and EJB's Stateful session bean are meant to maintain client state, so which one is a better option? let's look into the advantages and disadvantages of both the mechanisms :

    1 . Stateful session bean

        Advantages :

    • It supports transaction service ,security service, life cycle management, RMI, instance cache, thread safe etc. You need not write code for these services.

    • It can be used by both web based and non web based clients (like swing etc.) .

    • It can be used for multiple operations for a single http request.

        Disadvantages :

    • Since it supports a number of services mentioned above it takes more time to process a request.

    2.  HttpSession object

        Advantages:

    • It is a simple java object (perhaps a Hashtable) and takes very less time and resources to maintain a client state

        Disadvantages:

    • It does not support the features discussed above

    • It cannot process multiple operations for a single http request.

    So depending on your application's requirement you can choose the one best suited for you, if you want the bean only for client state management then HttpSession object gives better performance than Stateful session bean.

     

    Choosing an EJB server

    We have more than thirty vendors who provide EJB containers/servers. So when you have to choose  a server you need to carefully look into the following issues and consider the trade-offs between them. The following features need to be looked into before you decide on EJB server

    1. Clustering

    2. Load balancing

    3. Instance pool and instance caching

    4. Lazy loading

    5. Pass by reference for EJB 1.1

    6. Different locking strategies

    7. Connection pooling

    8. Controlling callback methods such as ejbLoad(),ejbStore() in CMP etc

    If an EJB server provides all these features  then how can you make sure about the performance of your server? The answer is to use the benchmarking specifications available such as TPC-W, @Bench etc and test the server. But  the problem with these bench marking policies is that they test only for a specific feature of your server, so in order to test the overall performance of your server you can use ECperf specification released by SUN to test your server.

    Ecperf benchmark specification is developed under java community process that is meant mainly for EJB server performance testing. It provides EJB code and driver to test an EJB server vigorously. For ECperf information, have a look at the following links

    http://java.sun.com/j2ee/ecperf/

    You will also find benchmark results of various servers at the following site.

    http://ecperf.theserverside.com/ecperf/

    http://www.cmis.csiro.au/adsat/

    In order to choose best EJB server, analyze features of different EJB servers, test using ECperf tool kit and see available benchmarks ( see above links for already available benchmarks) and finally decide suitable server for your application.

    Tuning Stateless session beans

    We already discussed common practices in the above sections. Those practices are applicable for Stateless session beans also. Here we discuss specific practices for Stateless session beans. In order to get clear picture of the practices, we will initially discuss Stateless session bean life cycle, since it drives some of the practices to improve performance. Note that the life cycle of all the beans are dissimilar.

    Stateless session bean life cycle

    Life cycle means when an EJBean is created and removed by EJB Container, and when the Container calls methods of EJBean. The following figure illustrates the life cycle of Stateless session bean.

    Stateless session bean figure

    You can control life cycle by mentioning instance pool size in vendor specific deployment descriptor. For example weblogic server's weblogic-ejb-jar.xml has element for instance pool size

    <pool>

            <max-beans-in-free-pool>100</max-beans-in-free-pool>

            <initial-beans-in-free-pool>50</initial-beans-in-free-pool>

    </pool>

    and JBoss server's jboss.xml has an element <instance-pool> to mention pool size. See vendors documentation for information for other servers. Here you can specify initial beans and maximum beans in pool. If you mention for example 50 beans in initial beans and 100 for maximum beans in the pool, the life cycle starts when the server starts up.

    When the server starts up, the EJB Container/Server creates 50 beans using Class.newInstance() method and puts it in the pool and it calls the following call back methods of the bean.

            setSessionContext(ctx) and

            ejbCreate() methods

    these 50 beans are ready to be accessed by 50 clients concurrently. If the client accesses exceed 50 then the Container creates beans and calls the above methods till the number of beans is equal to 100 (maximum beans in the pool). So at any time the Container can only have a maximum of 100 beans to serve clients. What will happen if the concurrent clients are more than 100? Then the container puts clients in the queue. We will discuss about this in the next section on how you can tune the pool size.

    The Container removes the beans from the pool if the number of clients accessing beans are less. When the Container removes the beans depending on its specific algorithms ( perhaps LRU, Least Recently Used). At this time Container calls ejbRemove() method of the bean.

    If the client calls the home.create() method,  the Container creates EJBObject and assigns existing bean from the pool to the the client, at this time client neither creates a bean nor calls ejbCreate() method because it is already called when it created and is put in the pool. In the same manner, if the client calls home.remove() / remote.remove() method, the Container removes EJBObject and deassigns the bean from the client and puts it back to the pool but does not remove from the pool. In Stateless session bean life cycle, Client does not have control over bean's life cycle and bean's call back methods, it does not know when the creation, destruction and call back methods occur. So In Stateless session beans the creation, destruction and call back methods depend upon the pool size, clients concurrent access and Container algorithms.

    As the name implies, a Stateless session bean does not maintain any state ( instance variables values) across methods, that is the reason why ejbActivate() and ejbPassivate() methods do not have significance in Stateless session bean. So the Container can assign different beans from the pool to the client for successive methods.

    With this discussion, we understand the importance of pool size and when the call back methods are executed in Stateless session beans. Now let us discuss how we can tune Stateless session beans.

    Tune Stateless session beans instance pool size

    The creation and destruction of beans is expensive. To reduce this cost, The EJB Container/Server creates pool of beans that depending upon vendor specific configuration, you need to give a proper value for this pool size to increase performance. As we discussed above, configure pool size, for example weblogic's weblogic-ejb-jar.xml has an element <pool> and JBoss server's jboss.xml has an element <instance-pool>. see your vendor documentation for configuring your EJB server pool size.

    The number of maximum beans in pool impacts performance. If this is less, then the Container has to put the clients in the queue when the number of clients accessing is more than the maximum pool size. This degrades the performance and clients take more time to execute. For best performance, give maximum beans as equal to number of maximum clients accesses.

    Use setSessionContext() or ejbCreate() method as cache

    In Stateless session bean life cycle, The container invokes the setSessionContext(SessionContext sc) and ejbCreate() methods when it creates the bean instance first time and puts it in the pool  and later it will be used for the other clients till it is removed by the Container,You can use these methods to acquire resources like home object references of other session or entity beans or DataSource references and put it in instance variables. Once you acquire these resources in these methods you need not acquire resources for each client because those resources are already acquired and available. Obviously these resources will be specific to a bean but not available globally. For global reuse, it is better to use the technique that we discussed in Cache EJBHome object references. You can use this technique to acquire other resources also. Remember that you should not acquire physical resources like database connections in these methods if the concurrent clients are more and pool size is more, it is better to acquire that type of resources in each method and remove them in that method. Use setSessionContext(SessionContext sc) and ejbCreate() methods to cache bean specific resources that are needed for other clients.

    Release resources in ejbRemove() method

    The Container calls ejbRemove() method just before removing a bean from the pool. So whatever resources you acquired in your bean like those discussed above must be released in this method. 

    Tuning Stateful session beans

    The common practices that we discussed above are applicable for Stateful session beans also. Here we discuss about specific practices for Stateful session beans. In order to get a clear picture, we will  initially discuss Stateful session bean's life cycle.

    Stateful session bean life cycle

    The life cycle of Stateful and Stateless bean is differs. The reason is, Stateful session bean has to maintain state (instance variables values) across the methods for a client. That means once a client assigns values for instance variables using one method, those values are available for other methods also. The following figure illustrates the life cycle of Stateful session bean.

    Figure7: Stateful session bean life cycle

    Stateful session bean figure

    Here you see the instance cache instead of instance pool. Cache maintains beans that have state (Stateful) whereas pool maintains beans that don't have state (Stateless). You can control life cycle by describing instance cache size in vendor specific deployment descriptor file. For example weblogic's weblogic-ejb-jar.xml has element for instance cache size

    <stateful-session-cache>

            <max-beans-in-cache>100</max-beans-in-cache>

    </stateful-session-cache>

    and JBoss server's jboss.xml has an element

    <instance-cache>

    <container-cache-conf>

            <cache-policy>

                    <cache-policy-conf>   

                              <min-capacity>5</min-capacity>       

                            <max-capacity>10</max-capacity>   

                 

                    </cache-policy-conf>   

            </cache-policy>

    </container-cache-conf>

    </instance-cache>

    For detailed information, look at their documentation and for other servers look at vendors documentation for instance cache configuration.

    Here you can specify minimum beans and maximum beans in cache. Some vendors such as weblogic do not support configuring minimum beans but support configuring maximum beans. So look at your vendor documentation for detailed information on what your EJB  Container/server supports.

    Here life cycle of stateful session bean starts when the client calls create() method. When the the client calls create() method, the Container creates the bean using Class.newInstance() and calls

            setSessionContext(ctx) and

            ejbCreate() methods

    and puts it in the instance cache. Then onwards, the client is assigned to that bean till client calls remove() method, thus container calls ejbRemove() and destroys the bean. In Stateful session bean, the client controls life cycle ( creation and removal but not activation and passivation). So when does container call ejbActivate() and ejbPassivate() methods? For example, if you set maximum beans in cache as 100 beans, when clients are accessing a bean concurrently, container creates beans till 100 (maximum bean limit) and assigns those beans to clients. After this limit, if the 101st client accesses this bean, Container passivates some of the idle beans that depending on Container algorithms. Just before passivating beans, it calls ejbPassivate() method. Here passivation means, it stores the bean's state (instance variables values) in the secondary storage (file storage or database). The passivation happens through Serialization. Later if the the idle client accesses the bean again, then Container activates the bean and reassigns the passivated values to its instance variables and calls ejbActivate() method.

    Here what we understand is that client controls creation and destruction of beans but not activation and passivation. Activation and passivation are controlled by Container and depend on instance cache size.

    With this discussion, we understand the importance of instance cache size and when the call back methods are executed in Stateful session beans. Now let us discuss how we can tune Stateful session beans.

    Tune Stateful session beans instance cache size

    As discussed above, You control activation and passivation indirectly by describing instance cache size in vendor specific deployment descriptor file . Activation and passivation is expensive because of serialization process. If the instance cache size is less and concurrent active clients are more than instance cache size then activation and passivation occur often, thus degrading performance. So in order to increase performance, give optimal cache size.

    Set optimal bean age for Stateful session beans

    The removal of EJBean instance by the Container from the instance cache depends not only on when the client calls remove() method but also on EJBean time out value (bean age) that you can configure in the vendor specific descriptor file. If the beans time out value is less, the Container needs to remove and create often,which is expensive. So set optimal bean age to minimise removal and creation process.

    Control Serialization in Stateful session beans

    We already discussed about Control Serialization in remote EJBs that describes how you need to control serialization when you pass method parameters from client to EJBean through network. Here we discuss about the serialization that is specific to Stateful session bean.

    When the Container wants to passivate a Stateful session bean it needs to serialize the instance variable values and store it in the secondary storage and needs to de-serialize those values from storage when it activates. The Serialization occurs for all instance variables except 'transient' variables. If the instance variable has a huge object graph, you may not want to serialize total graph or all the instance variables. So to avoid serialization for unwanted variables, use 'transient' keyword for those variables so that serialization process will be reduced. For more detailed information about serialization, See the Serialization section.

    Remove Stateful session beans explicitly

    The Container keeps the bean in the instance cache till the bean's time out occurs or when the client calls remove() method explicitly otherwise the container passivates the bean if the bean is idle for more time. So if the client finishes work with the bean and does not remove explicitly, the Container keeps the the bean in the instance cache or passivates the bean. This process consumes unnecessary memory. So remove the bean explicitly from the client using the remove() method.

    June 03

    Java is 10

    Happy 10th Birthday, Java Technology! Happy 10th Birthday, Java Technology!

    CELEBRATE THE POWER OF JAVA TECHNOLOGY!
    1995 to 2005... and Beyond!

    On May 17, 2005, Java technology celebrated its 10th birthday, and we could not be more excited! Ten years ago, Java technology was brand new, exciting but unproven, though the opportunity was huge. For consumers, developers, businesses large and small, and even governments, Java technology has fundamentally changed the way we interact with our computers, the Internet, and each other--all around the world.

    So, we say "Happy 10th birthday, Java technology, and congratulations!" Congratulations for becoming one of the most pervasive and useful technologies around the world. Congratulations for becoming a household name. Congratulations for creating a tight-knit community of consumers, developers and businesses, numbering in the tens of millions, eager to make the world of computing more useful, more secure and more fun. All in just ten years. See the related article, "A Java Team Member Remembers the Early Days."

    Java technology's impact on communities and industries around the world is undeniable. Today, you can find Java technology in networks and devices that range from the Internet and scientific supercomputers to laptops and cell phones, from Wall Street market simulators to home game players, credit cards, automobiles, the Mars Rover -- just about everywhere. Here are some examples of Java technology's reach:

      139+ million Java software downloads from java.com
      4.5+ million Java software developers worldwide
      140+ global wireless carriers providing mobile Java services
      579+ million Java Powered mobile phones
      825+ million Java Cards

    Maybe you didn't know all the ways Java technology is enhancing millions of lives, products, services and organizations. But there are many great places to find out more, including right here on java.com. Won't you please check out some of the exciting links below? You'll soon understand why so many people are excited about Java technology's exciting past and brilliant future. And you, too, may find yourself wishing Java technology a very happy 10th birthday!

    Best Wishes,
    The java.com Team



    June 02

    Best practices for closing ResultSet and CallableStatement within loop

    The finally Block

    The final step in setting up an exception handler is to clean up before allowing control to be passed to a different part of the program. You do this by enclosing the clean up code within a finally block. The finally block is optional and provides a mechanism to clean up regardless of what happens within the try block. Use the finally block to close files or to release other system resources.

    The try block of the writeList method that you’ve been working with here opens a PrintWriter. The program should close that stream before exiting the writeList method. This poses a somewhat complicated problem because writeList’s try block can exit in one of three ways.

    1. The new FileWriter statement fails and throws an IOException.
    2. The victor.elementAt(i) statement fails and throws an ArrayIndexOutOfBoundsException.
    3. Everything succeeds and the try block exits normally.
    The runtime system always executes the statements within the finally block regardless of what happens within the try block. So it’s the perfect place to per­form cleanup.

    The following finally block for the writeList method cleans up and closes the PrintWriter.

    finally { if (out != null) { System.out.println("Closing PrintWriter"); out.close(); } else { System.out.println("PrintWriter not open"); } }
    In the writeList example, you could provide for cleanup without the intervention of a finally block. For example, you could put the code to close the PrintWriter at the end of the try block and again within the exception handler for ArrayIndexOutOfBoundsException, as shown here:
    try { ... out.close(); // don't do this; it duplicates code } catch (FileNotFoundException e) { out.close(); // don't do this; it duplicates code System.err.println("Caught: FileNotFoundException: " + e.getMessage()); throw new RuntimeException(e); } catch (IOException e) { System.err.println("Caught IOException: " + e.getMessage()); }

    However, this duplicates code, thus making the code difficult to read and error prone if you later modify it. For example, if you add to the try block code that can throw a new type of exception, you have to remember to close the PrintWriter within the new exception handler.

     

    http://java.sun.com/docs/books/tutorial/essential/exceptions/finally.html

     

    Best practices for closing ResultSet and CallableStatement within loop.
    Author: lesoft Feb 4, 2005 2:37 PM
    Hi,

    I have the code below and it's run fine. I would like to know whether it's the correct way to close the ResultSet and Statement within a loop.

    Let's say I have a loop that calls the same stored proc to query record. It goes thru the loop 5 times and each time it passes in an index value, ie: 1, 2, 3, 4, 5. Right now, I close the ResultSet and CallableStatement at the end of my for loop (see bold statement below). Is that the right place for closing the database resources to provide better performance?

    ResultSet rs = null; CallableStatement cs = null; Connection conn = null; try { conn = getConnection(); String query = "{?= call my_stored_proc(?)}"; cs = conn.prepareCall(query); cs.registerOutParameter(1, Types.INTEGER); HashMap report = new HashMap(); for (int i = 1; i <= 5; i++) { cs.setInt(2, i); rs = cs.executeQuery(); if (rs != null && rs.first()) { // get the data from resultset here... } [b]rs.close();[/b] [b]cs.close();[/b] } // end for loop } catch (SQLException e) { // error !!! } finally { // release object's database and JDBC resources rs.close(); cs.close(); conn.close(); }

    Thanks,
    Tuan
     
    Re: Best practices for closing ResultSet and CallableStatement within loop.
    Author: jschell Feb 4, 2005 3:13 PM (reply 1 of 8)
    First you should try to get a solution that doesn't require you to call it multiple times in the first place. That would make the performance better.

    Second the finally block closes it. You don't need it after the loop.
     
    Re: Best practices for closing ResultSet and CallableStatement within loop.
    Author: lesoft Feb 4, 2005 3:29 PM (reply 2 of 8)
    Thanks for your quick response!

    In my case, I don't think there's a better performance solution. For example, I have an input of an array of 20 student IDs and I need to call a stored procedure to query all 20 student records and store them in my student collection object. If you know of a better solution, please share.

    Also, I thought I have seen a posted msg in one of the forums that recommended to close ResultSet and CallableStatement within a loop. Yes, the finally block would close them for sure.

    Thanks,
    Tuan
     
    Re: Best practices for closing ResultSet and CallableStatement within loop.
    Author: jschell Feb 4, 2005 4:07 PM (reply 3 of 8)
    > Thanks for your quick response!
    >
    > In my case, I don't think there's a better
    > performance solution. For example, I have an input of
    > an array of 20 student IDs and I need to call a
    > stored procedure to query all 20 student records and
    > store them in my student collection object. If you
    > know of a better solution, please share.

    So 20 calls.

    1. So create a proc that takes 5 ids rather than 1. Then you only need 4 calls.

    2. Use an array, which depends on the database and specific code, to pass all 20 at once. Only 1 call.

    3. Create a string with all 20 ids. Pass that to a proc. Have the proc parse the string and returns the results for all of them. Only 1 call.

    >
    > Also, I thought I have seen a posted msg in one of
    > the forums that recommended to close ResultSet and
    > CallableStatement within a loop. Yes, the finally
    > block would close them for sure.

    Sorry I missed that.

    You can't close the statement in the loop regardless. If you do you have to create it again. And there is no point in that and it will probably be slower if you do so.

    You can close the result set in the loop. It won't have any impact.

    And once you are outside the loop then the finally block closes the statement. So you don't need the one just outside the loop (which is where it should be and I thought it was in my first response.)
     
    Re: Best practices for closing ResultSet and CallableStatement within loop
    Author: lesoft Feb 5, 2005 9:41 AM (reply 4 of 8)
    Hi jschell,

    Thanks again for your help! Regarding your solution to getting 20 student records it 's very helpful and I will change my code to do as you suggested.

    Regarding closing the ResultSet if I don't close the ResultSet within the loop, when it iterates thru the next index in the loop does that create another ResultSet or does it resuse the same resultSet over again?

    Thanks,
    Tuan
     
    Re: Best practices for closing ResultSet and CallableStatement within loop
    Author: sjasja Feb 5, 2005 10:32 AM (reply 5 of 8)
    The suggestions for reducing the number of round trips to the server are all good.

    If you still end up needing to close a ResultSet or a Statement within a loop, do this:
    for (...) { res = ...; while (res.next()) ...; res.close(); res = null; stmt.close(); // Don't close if it is a PreparedStatement and you use it on the next iteration stmt = null; }   } finally { try { if (res != null) res.close(); } catch (SQLException e) { ...log it... } try { if (stmt != null) stmt.close(); } catch (SQLException e) { ...log it... } try { if (connection != null) ..return to pool...; } catch (SQLException e) { ...log it... } }
    You need to set res and stmt to null so that they don't get closed again in finally. You need the "if (res != null)" checks in finally because res can be null if e.g. prepareCall() throws an exception. You need the try/catch blocks in finally because if closing res throws an exception, you don't want to exit the finally block, you want to close stmt and connection.

    I like having static "Util.close(res)" etc methods so I don't have to re-re-re-type the if/try/catch stuff in the finally. There is a bug in that though: if closing res fails, the error gets logged but otherwise ignored. A better way would be to have a method Util.close(res, stmt, connection) that closes all three no matter what, and if any of the closes fail, re-throws the exception after all three have been closed. Implementation left as an exercise to the reader.
     
    Re: Best practices for closing ResultSet and CallableStatement within loop
    Author: lesoft Feb 5, 2005 10:47 AM (reply 6 of 8)
    Would you please explain to me the differences (if any) between the two sets of code below regarding utilizing database resource

    Version 1
    ResultSet rs = null; CallableStatement cs = null; Connection conn = null; try { conn = getConnection(); String query = "{?= call my_stored_proc(?)}"; cs = conn.prepareCall(query); cs.registerOutParameter(1, Types.INTEGER); HashMap report = new HashMap(); for (int i = 1; i <= 5; i++) { cs.setInt(2, i); rs = cs.executeQuery(); if (rs != null && rs.first()) { // get the data from resultset here... } // DON'T CLOSE ResultSet and CallableStatement } // end for loop } catch (SQLException e) { // error !!! } finally { // release object's database and JDBC resources rs.close(); cs.close(); conn.close(); }

    Version 2
    ResultSet rs = null; CallableStatement cs = null; Connection conn = null; try { conn = getConnection(); String query = "{?= call my_stored_proc(?)}"; cs = conn.prepareCall(query); cs.registerOutParameter(1, Types.INTEGER); HashMap report = new HashMap(); for (int i = 1; i <= 5; i++) { cs.setInt(2, i); rs = cs.executeQuery(); if (rs != null && rs.first()) { // get the data from resultset here... } // CLOSE ResultSet and CallableStatement rs.close(); cs.close(); } // end for loop } catch (SQLException e) { // error !!! } finally { // release object's database and JDBC resources rs.close(); cs.close(); conn.close(); }

    Thanks,
    Tuan
     
    Re: Best practices for closing ResultSet and CallableStatement within loop
    Author: jschell Feb 5, 2005 3:07 PM (reply 7 of 8)
    > Hi jschell,
    >
    > Thanks again for your help! Regarding your solution
    > to getting 20 student records it 's very helpful and
    > I will change my code to do as you suggested.
    >
    > Regarding closing the ResultSet if I don't close the
    > ResultSet within the loop, when it iterates thru the
    > next index in the loop does that create another
    > ResultSet or does it resuse the same resultSet over
    > again?

    It is highly likely that it will create another one regardless of what you do.

    It should also close the previous one when it creates the new one, but I would not rely on that.
     
    Re: Best practices for closing ResultSet and CallableStatement within loop
    Author: jschell Feb 5, 2005 3:13 PM (reply 8 of 8)
    > Would you please explain to me the differences (if
    > any) between the two sets of code below regarding
    > utilizing database resource

    One thing is that the first one will work and the second will not.

    Once you close a resource you can't use it again. And you are closing the statement. (Closing the result set is not the same because there is a new one each time.)

    And closing something twice probably isn't a good idea, mostly because it do nothing or it might produce an exception.

    However in the first version you don't close each result set. That might work but if it was me I wouldn't take the chance.

    And the previous suggestion (setting it to null) allows you to protect from closing anything twice.

    WLS8.1 on solaris Too Many Open Files - FD problem

    /dev_app/bea/weblogic81/common/bin/commEnv.sh

    FUNCTION  resetFd()

    .........

    # limit the number of open file descriptors
    resetFd() {
      if [ ! -n "`uname -s |grep -i cygwin || uname -s |grep -i windows_nt`" ]
      then
        maxfiles=`ulimit -H -n`
        if [ "$?" = "0" -a "${maxfiles}" != 1024 ]; then
          if [ "${maxfiles}" = "unlimited" ]; then
            maxfiles=1025
          fi
          if [ "${maxfiles}" -lt 1024 ]; then
            ulimit -n ${maxfiles}
          else
            ulimit -n 1024
          fi
        fi
      fi
    }

    .......

    .............

    check_pfiles
    =======

    #!/usr/bin/sh

    while true
    do
    date >> total_open_files.txt
    pfiles 13803|grep size|wc -l >> total_open_files.txt
    #ls -lart /proc/$1/fd|wc -l >> total_open_files.txt
    sleep 1800
    done

    check_lsof
    ======

    #!/usr/bin/sh

    while true
    do
    date >> total_fd.txt
    ls -lart /proc/13803/fd|wc -l >> total_fd.txt
    sleep 1800
    done

     

    postprint

    Solaris Printing Capabilities

    The program described here will only work with PostScript capable printer.

    Under Solaris 2.x Sun provides a program called postprint, for PostScript printing. This program resides in /usr/lib/lp/postscript. Here I'll cover only the more interesting options to postprint if you need to know more about this program check out the man pages for postprint.

    For example to print a file in landscape mode use the following command:

    /usr/lib/lp/postscript/postprint -p land filename | lp -c num This option prints num copies of the file -n num Print num logical pages on one physical page. Referred to as NUP (n-up) on some platforms. -p mode Print the pages in either portrait or landscape mode. You can use the full name of the mode or abbreviate it to just the first character. -t num Sets a tab stop every num characters. The default for num is 8.

     http://www.barbary.com/cookbooks/printing.html

    June 01

    《棋子》

       《棋子》 举棋不定

    想走出你控制的领域
    却走进你安排的战局
    我没有坚强的防备
    也没有后路可以退
    想逃离你佈下的陷阱
    却陷入了另一个困境
    我没有决定输赢的勇气
    也没有逃脱的幸运
    我像是一颗棋
    进退任由你决定
    我不是你眼中唯一 将领
    却是不起眼的小兵
    我像是一颗棋
    来去全不由自己
    举手无回你从不曾犹豫
    我却 受控在你手里

    May 31

    Using a Run Control Script to Stop or Start Services

    Note - The way system services are started and stopped in Solaris environment might change in some future release.

    One advantage of having individual scripts for each run level is that you can run scripts in the /etc/init.d directory individually to stop system services without changing a system's run level.

    ProcedureHow to Use a Run Control Script to Stop or Start a Service
    1. Become superuser.

    2. Stop the system service.

      # /etc/init.d/filename stop
    3. Restart the system service.

      # /etc/init.d/filename start
    4. Verify that the service has been stopped or started.

      # pgrep -f service
    Example--Using a Run Control Script to Stop or Start a Service

    For example, you can stop the NFS server daemons by typing the following:

    # /etc/init.d/nfs.server stop # pgrep -f nfs #

    Then, you can restart the NFS server daemons by typing the following:

    # /etc/init.d/nfs.server start # pgrep -f nfs 341 343 347 345 # pgrep -f nfs -d, | xargs ps -fp UID PID PPID C STIME TTY TIME CMD daemon 341 1 0 Aug 21 ? 0:00 /usr/lib/nfs/statd root 343 1 0 Aug 21 ? 0:00 /usr/lib/nfs/lockd root 347 1 0 Aug 21 ? 0:41 /usr/lib/nfs/nfsd root 345 1 0 Aug 21 ? 0:02 /usr/lib/nfs/mountd

    Adding a Run Control Script

    Note - The way system services are started and stopped in the Solaris environment might change in some future release.

    If you want to add a run control script to start and stop a service, copy the script into the /etc/init.d directory. Then, create links in the rcn.d directory where you want the service to start and stop.

    See the README file in each /etc/rcn.d directory for more information on naming run control scripts. The following procedure describes how to add a run control script.

    ProcedureHow to Add a Run Control Script
    1. Become superuser.

    2. Add the script to the /etc/init.d directory.

      # cp filename /etc/init.d # chmod 0744 /etc/init.d/filename # chown root:sys /etc/init.d/filename
    3. Create links to the appropriate rcn.d directory.

      # cd /etc/init.d # ln filename /etc/rc2.d/Snnfilename # ln filename /etc/rcn.d/Knnfilename
    4. Verify that the script has links in the specified directories.

      # ls /etc/init.d/ /etc/rc2.d/ /etc/rcn.d/
    Example--Adding a Run Control Script

    The following example shows how to add a run control script for the xyz service.

    # cp xyz /etc/init.d # chmod 0744 /etc/init.d/xyz # chown root:sys /etc/init.d/xyz # cd /etc/init.d # ln xyz /etc/rc2.d/S100xyz # ln xyz /etc/rc0.d/K100xyz # ls /etc/init.d /etc/rc2.d /etc/rc0.d

    Disabling a Run Control Script

    You can disable a run control script by renaming it with an underscore (_) at the beginning of the file name. Files that begin with an underscore or dot are not executed. If you copy a file by adding a suffix to it, both files will be run.

    ProcedureHow to Disable a Run Control Script
    1. Become superuser.

    2. Rename the script by adding an underscore (_) to the beginning of the new file.

      # cd /etc/rcn.d # mv filename _filename
    3. Verify that the script has been renamed.

      # ls _* # _filename
    Example--Disabling a Run Control Script

    The following example shows how to rename the S100datainit script.

    # cd /etc/rc2.d # mv S100datainit _S100datainit # ls _* # _S100datainit

    x86: Boot Files

    In addition to the run control scripts and boot files described previously, there are additional boot files that are associated with booting a Solaris x86 system.

    Table 11-5 x86: Boot Files

    File

    Description

    /etc/bootrc

    Contains menus and options for booting the Solaris release.

    /boot

    Contains files and directories needed to boot the system.

    /boot/mdboot

    DOS executable that loads the first-level bootstrap program (strap.com) into memory from disk.

    /boot/mdbootbp

    DOS executable that loads the first-level bootstrap program (strap.com) into memory from diskette.

    /boot/rc.d

    Directory that contains install scripts. Do not modify the contents of this directory.

    /boot/solaris

    Directory that contains items for the boot subsystem.

    /boot/solaris/boot.bin

    Loads the Solaris kernel or standalone kadb. In addition, this executable provides some boot firmware services.

    /boot/solaris/boot.rc

    Prints the Solaris x86 Platform Edition and runs the Device Configuration Assistant in DOS-emulation mode.

    /boot/solaris/bootconf.exe

    DOS executable for the Device Configuration Assistant.

    /boot/solaris/bootconf.txt

    Text file that contains internationalized messages for Device Configuration Assistant (bootconf.exe).

    /boot/solaris/bootenv.rc

    Stores eeprom variables that are used to set up the boot environment.

    /boot/solaris/devicedb

    Directory that contains the master file, a database of all possible devices supported with realmode drivers.

    /boot/solaris/drivers

    Directory that contains realmode drivers.

    /boot/solaris/itup2.exe

    DOS executable run during install time update (ITU) process.

    /boot/solaris/machines

    Obsolete directory.

    /boot/solaris/nbp

    File associated with network booting.

    /boot/solaris/strap.rc

    File that contains instructions on what load module to load and where in memory it should be loaded.

    /boot/strap.com

    DOS executable that loads the second-level bootstrap program into memory.

    Previous Previous     Contents     Index     Next Next

    http://docsun.cites.uiuc.edu/sun_docs/C/solaris_9/SUNWaadm/SYSADV1/p38.html

    Essential Elements for Any Successful Project

    What Exactly Is a "Successful" Project?

    You would think it would be relatively straightforward to describe the attributes of a successful project. Well, let’s just say this endeavor has kept more than a few "spin doctors," "politicians," and "history revisionists" employed throughout organizations across our great land. Why is this the case? There are several reasons for this.

    • There is a lack of universal harmony of what comprises project success metrics. It seems that every project management educational source and organizational process maturity standard has a slightly different definition of project success.

    • For many projects, the acceptance and success criteria are never established or agreed to by all key stakeholders.

    • In many cases, an organization may define a project as successful even when some of the textbook criteria for project success (such as schedule, cost, client expectations) are not completely met.

    • In other cases, a "cancelled" project may be a "successful" project if there was a plan for one or more "go/no-go" decision points.

    From a utopian, academic standpoint, the "ultimate" successful project would be defined as a project that:

    • Delivered as promised—Project produced all the stated deliverables.

    • Completed on-time—Project completed within the approved schedule.

    • Completed within budget—Project completed under the approved budget.

    • Delivered quality—Project deliverables met all functional, performance, and quality specifications.

    • Achieved original purpose—The project achieved its original goals, objectives, and purpose.

    • Met all stakeholder expectations—The complete expectations of each key stakeholder were met, including all client acceptance criteria, and each key stakeholder accepts the project results without reservation.

    • Maintains "win-win" relationships—The needs of the project are met with a "people focus" and do not require sacrificing the needs of individual team members or vendors. Participants on successful projects should be enthusiastic when the project is complete and eager to repeat a similar experience.

    TIP

    An excellent technique is to identify, document, review, and approve any criteria that will be used to measure the success of the project during the project definition and planning processes.

    Solaris 9 System Startup and Shutdown

    rc Scripts

    Each init state has a corresponding series of run control scripts—which are referred to as rc scripts and are located in the /sbin directory—to control each init state. These rc scripts are as follows:

    • rc0

    • rc1

    • rc2

    • rc3

    • rc5

    • rc6

    • rcS

    NOTE

    Run Control Scripts Many of the Solaris startup scripts can be identified by their rc prefix or suffix, which means run control.

    The init process executes the /sbin/rc<n> scripts, which in turn execute a series of other scripts that are located in the /etc directory. For each rc script in the /sbin directory, a corresponding directory named /etc/rc<n>.d contains scripts to perform various actions for that run level. For example, /etc/rc2.d contains files that are used to start and stop processes for run level 2.

    NOTE

    /etc/init.d Although the scripts appear as files in each directory, the rc<n>.d directories contain hard links to the /etc/init.d directory. On other Unix systems, startup scripts are sometimes found in /sbin/rc<n>.d and in /etc/rc<n>.d directories. Links were put into Solaris so that users who are accustomed to other flavors of Unix (HP-UX, SunOS, and so on) can locate the startup files easily. In addition, any scripts they might have ported over that reference these startup files are compatible, without modification. Also, by putting all the scripts in one location, /etc/init.d, it's convenient to find the script needed to start or stop a particular function without searching through all the /etc/rc<n>.d directories.

    All run control scripts are also located in the /etc/init.d directory, and all scripts must be /sbin/sh scripts. These files are linked to corresponding run control scripts in the /etc/rc<n>.d directories.

    The following is a list of the default scripts located in /etc/rc2.d, which are put there when the operating system is installed:

    ls /etc/rc2.d K03samba S05RMTMPFILES S72autoinstall S80spc K03sshd S10lu S72directory S85power K06mipagent S20sysetup S72inetsvc S88sendmail K07dmi S21perf S72slpd S88utmpd K07snmpdx S30sysid.net S73cachefs.daemon S89PRESERVE K16apache S40llc2 S73nfs.client S89bdconfig K21dhcp S42ncakmod S74autofs S90wbem K27boot.server S47pppd S74syslog S92volmgt K28kdc S69inet S74xntpd S93cacheos.finish K28kdc.master S70uucp S75cron S94ncalogd K28nfs.server S71ldap.client S75savecore S95svm.sync README S71rpc S76nscd S99audit S01MOUNTFSYS S71sysid.sys S80lp S99dtlogin

    As you'll learn in the section "Adding Scripts to the Run Control Directories," later in this chapter, you can add customized scripts to this directory. The /etc/rc<n>.d scripts are always run in ASCII sort order shown by the ls command and have names of this form:

    [K,S][#][filename]

    A file that begins with K is referred to as a stop script and is run to terminate (kill) a system process. A file that begins with S is referred to as a start script and is run to start a system process. Each of these start and stop scripts is called by the appropriate /sbin/rc# script, which passes the argument start or stop to each script, based on their prefix and whether the name ends in .sh. There are no arguments passed to scripts that end in .sh. The actions of the different run-control-level scripts are summarized in the following lists.

    The /sbin/rc0 script runs the /etc/rc0.d scripts, which do the following:

    • Stop system services and daemons.

    • Terminate all running processes.

    • Unmount all file systems.

    The /sbin/rcS script runs the /etc/rcS.d scripts to bring the system up to single-user mode and to do the following:

    • Establish a minimal network.

    • Mount /usr, if necessary.

    • Set the system name.

    • Check the / and /usr file systems.

    • Mount pseudo file systems (/proc and /dev/fd).

    • Rebuild the device entries (for reconfiguration boots).

    • Check and mount other file systems to be mounted in single-user mode.

    init state S is similar to run level 1, except that in init state S all local file systems get mounted and are accessible.

    TIP

    Keeping Users Off the System You should use the init state S run level to perform system administration tasks when you want to ensure that other users cannot log in and access the system.

    The /sbin/rc1 script runs the /etc/rc1.d scripts and does the following:

    • Stops system services and daemons except for the most basic operating system services

    • Enables all file systems to be available and allows any logged-in users to remain logged in

    • Brings up the system in single-user mode

    • Performs initial system startup or final system shutdown for a Solaris Live Upgrade.

    The /sbin/rc2 script sets the TIMEZONE variable, runs the /etc/rc2.d scripts, and does the following:

    • Mounts all file systems

    • Enables disk quotas if at least one file system was mounted with the quota option

    • Saves editor temporary files in /usr/preserve

    • Removes any files that are in the /tmp directory

    • Configures system accounting

    • Configures the default router

    • Sets the Network Information Services (NIS) domain

    • Sets the ifconfig netmask

    • Reboots the system from the installation media or a boot server if either /.PREINSTALL or /AUTOINSTALL exists

    • Starts inetd, rpcbind, and named, if appropriate

    • Starts the Kerberos client-side daemon (kerbd)

    • Starts NIS daemons (ypbind) and Network Information Services Plus (NIS+) daemons (rpc.nisd), if appropriate

    • Starts keyserv

    • Starts statd, lockd, xntpd, vold, and utmpd

    • Mounts all NFS entries

    • Starts automount

    • Starts cron

    • Starts the lp daemons

    • Starts the sendmail daemon

    • Starts the name service cache daemon (nscd)

    • Starts syslog

    The /sbin/rc3 script runs the /etc/rc3.d scripts and does the following:

    • Cleans up sharetab

    • Starts nfsd

    • Starts mountd

    • Starts the master Simple Network Message Protocol (SNMP) agent, snmpdx, and the Solstice Enterprise Agents

    • Starts rarpd, rpld, and rpc.bootparamd if the system is a boot server

    The /sbin/rc5 and /sbin/rc6 scripts run the /etc/rc0.d scripts and do the following:

    • Kill all active processes.

    • Unmount all file systems.

    Using the Run Control Scripts to Stop or Start Services

    The advantage of having individual scripts for each run level is that you can run these scripts individually to turn off processes in Solaris without rebooting or changing init states.

    For example, you can turn off NFS server functionality by typing /etc/init.d/nfs.server stop and pressing Enter. After you have changed the system configuration, you can restart the functionality by typing /etc/init.d/nfs.server start and pressing Enter.

    You can use the pgrep command to verify whether a service has been stopped or started:

    pgrep -f <service>

    The pgrep utility examines the active processes on the system and reports the process IDs of the processes. See Chapter 5, "Managing System Processes," for details on this command.

    Adding Scripts to the Run Control Directories

    When you add a script to the run control directories, you put the script in the /etc/init.d directory and create a link to the appropriate rc<n>.d directory. You need to assign appropriate numbers and names to the new scripts so that they will be run in the proper ASCII sequence, as described in the previous section.

    To add a new run control script to a system, follow the process in Step by Step 3.2.

    Step by Step 3.2: Adding a Run Control Script
    1. Become the superuser.

    2. Add the script to the /etc/init.d directory:

      # cp <filename> /etc/init.d # cd /etc/init.d # chmod 744 <filename> # chown root:sys <filename>
    3. Create links to the appropriate rc<n>.d directory:

      # ln <filename> /etc/rc2.d/S<nnfilename> # ln <filename> /etc/rc<n>.d/K<nnfilename>
    4. Use the ls command to verify that the script has links in the specified directories:

      # ls –li /etc/init.d/*<filename> /etc/rc?.d/[SK]*<filename>

    The following example creates an rc script named program that starts up at run level 2 and stops at run level 0. Note the use of hard links versus soft links:

    # cp program /etc/init.d # cd /etc/init.d # chmod 744 program # chown root:sys program # ln /etc/init.d/program /etc/rc2.d/S100program # ln /etc/init.d/program /etc/rc0.d/K100program

    You can verify the links by typing this:

    # ls -li /etc/init.d/*program /etc/rc?.d/[SK]*program

    The system displays the following:

    389928 -rwxr--r-- 3 root sys 69 Oct 26 23:31 /etc/init.d/program 389928 -rwxr--r-- 3 root sys 69 Oct 26 23:31 /etc/rc0.d/K77program 389928 -rwxr--r-- 3 root sys 69 Oct 26 23:31 /etc/rc2.d/S77program

    NOTE

    Disabling a Run Control Script If you do not want a particular script to run when the system is entering a corresponding init state, you can change the uppercase prefix (S or K) to some other character; I prefer lowercase (s or k). Only files with uppercase prefixes of S or K are run. For example, you could change S99mount to s99mount to disable the script.

     

     

    Marratech Portal

    Linux and Solaris

    Install marratech.sh as /etc/init.d/marratech and link it to

    the appropriate startup directory.

    This script should work under both Linux and Solaris.

    Example: ln -s /etc/init.d/marratech /etc/rc3.d/S10marratech#!/bin/sh
    # This is an example KILL/START script for Sun Solaris 8.
    # Modify it according to your needs.
    #
    # Example:
    # This script is stored as /etc/init.d/marratechportal and
    # linked from /etc/rc3.d/S98marratechportal and
    # /etc/rc{0,1,2,3}.d/K02marratechportal .DIR="$USER_INSTALL_DIR$" NAME="Marratech E-meeting Portal 1.3"case "$1" in 'start') echo "Starting $NAME" $DIR/bin/MarratechPortal > /dev/null 2>&1 & ;;'stop') echo "Stopping $NAME" /usr/bin/pkill -9 -u 0 -f "$DIR/jre/bin/java" > /dev/null 2>&1 ;;'restart') echo "Restarting $NAME" $0 stop $0 start ;;'shutdown') echo "Shutting down $NAME" echo 'shutdown -t NOW' | $DIR/bin/mAdminShell > /dev/null 2>&1 ;;*) echo "Usage: $0 {start|stop|restart|shutdown}" exit 1 ;;esac exit 0
    May 30

    开始懂了_孙燕姿

     《开始懂了》

    我竟然没有调头
    最残忍那一刻
    静静看你走
    一点都不像我
    原来人会变得温柔
    是透澈的懂了
    爱情是流动的
    不由人的
    何必激动着要理由
    相信你只是怕伤害我
    不是骗我
    很爱过谁会舍得
    把我的梦摇醒了
    宣布幸福不会来了
    用心酸微笑去原谅了
    也翻越了
    有昨天还是好的
    但明天是自己的
    开始懂了

     

    寂寞當然有一點 你不在我身邊 總是特別想念你的臉

    距離是一份考卷 測量相愛的誓言 最后會不會實現

    我們為愛還在學 學溝通的語言 學著諒解 學著不流淚

    等到我們學會飛 飛越黑夜 和考驗 日子就要從孤單里畢業

    我們用多一點點的辛苦 來交換多一點點的幸福 就算

    幸福 還有一段路 等我們學會忍耐和付出

    這愛情一定會有張証書 証明 從此 不孤獨

     

    《以父之名》

     周杰伦《以父之名》
    微凉的晨露沾湿黑礼服石板路有雾父在低诉
    无奈的觉悟只能更残酷一切都为了通往圣堂的路
    吹不散的雾隐没了意图谁轻柔踱步停住
    还来不及哭穿过的子弹就带走温度
    我们每个人都有罪犯著不同的罪
    我能决定谁对谁又该要沈睡
    争论不能解决在永无止境的夜
    关掉你的嘴唯一的恩惠
    挡在前面的人都有罪後悔也无路可退
    以父之名判决那感觉没有适合字汇
    就像边笑边掉泪凝视著完全的黑
    阻挡悲剧蔓延的悲剧会让我沈醉
    *低头亲吻我的左手换取被宽恕的承诺
    老旧管风琴在角落一直一直一直伴奏
    黑色帘幕被风吹动阳光无言的穿透
    洒向那群被我驯服後的兽
    沈默的喊叫沈默的喊叫孤单开始发酵
    不停对著我嘲笑回忆逐渐延烧
    曾经纯真的画面残忍的温柔出现脆弱时间到我们一起来祷告
    #仁慈的父我已坠入看不见罪的国度请原谅我的自负
    没人能说没人可说好难承受荣耀的背後刻著一道孤独
    闭上双眼我又看见当年那梦的画面天空是蒙蒙的雾
    父亲牵著我的双手轻轻走过清晨那安安静静的石板路
    repeat *,#
    (仁慈的父我已坠入看不见罪的国度
    请原谅我我的自负刻著一道孤独)
    repeat #
    那斑驳的家徽我擦拭了一夜孤独的光辉我才懂的感觉
    烛光不不停的摇晃猫头鹰在窗棂上对著远方眺望
    通向大厅的长廊一样说不出的沧桑
    没有喧嚣只有宁静围绕我慢慢睡著天刚刚破晓


    -------The End-------

    Create a jsp with input to enter stock

    Here's how you how to create a Web page that has an input form for a user to enter in a stock symbol and get the current stock price (delayed by 20 minutes). If there is an error, an error page is shown instead.

    quote.jsp
    First, create a quote.jsp page with the code below and save it in the Web pages directory under the JSWDK installation directory. Most of the page is standard HTML with JSP code interspersed. Line 6 is a page directive that says to send any error to the errorPage.jsp file. Lines 13 through 15 are a scriptlet that basically says only show the table if the "symbol" parameter is present. This if-block is closed on lines 32 through 34. Line 17 defines the JavaBean to use, and line 18 loads its symbol property from the parameter. Lines 27 through 29 just display the bean properties. Other than the if-block, there is really no Java coding involved.

    <html>
    <head>
    <title>Stock Quotes</title>
    </head>
    <body>
    <%@ page errorPage="errorPage.jsp" %>
    <form action="quote.jsp"
    method="GET"> <p>Enter Symbol: <input size="20" name="symbol"><input
    type="submit" value="Submit"></p>
    </form>
    <%if (request.getParameter("symbol") != null) {
    %>
    <jsp:useBean id="quotes" scope="page" class="com.jguru.Quotes" />
    <jsp:setProperty name="quotes" property="*" />
    <table border="1">
    <tr>
    <th align="left">Symbol</th>
    <th align="left">Name</th>
    <th align="left">Price</th>
    </tr>
    <tr>
    <td><jsp:getProperty name="quotes" property="symbol" /></td>
    <td><jsp:getProperty name="quotes" property="name" /></td>
    <td><jsp:getProperty name="quotes" property="price" /></td>
    </tr>
    </table>
    <%
    }
    %>
    </body>
    </html>

    errorPage.jsp
    Next, save the following JSP source to the file errorPage.jsp in the Web pages directory. The clue that this is an error page is the first line, which sets the page directive isErrorPage attribute to true. Whereas the prior page said where the error page is, this page says it is the error page. The only other JSP-specific code in the JSP file is the access to the implicit exception object. The page just displays its value:

    <%@ page isErrorPage="true" %>
    <html>
    <head>
    <title>Error Page</title>
    </head>
    <body>
    <h1>Our Error Page</h1></font>
    <!-- Print Exception -->
    We got ourselves an exception:
    <%= exception %>
    <a href="quote.jsp">Restart</a>
    </body>
    </html>

    Quotes.java
    The Quotes JavaBean uses a Yahoo resource to get the stock pricing. Save the Quotes.java source (below) in the quotes.java file in the classes\com\jguru directory under the JSWDK installation directory. From there, compile it with the javac compiler from the JSDK.

    package com.jguru;

    import java.util.*;
    import java.net.*;
    import java.io.*;

    public class Quotes {
      String symbol;
      String name;
      String price;
      public void setSymbol(String symbol) {
        this.symbol = symbol;
        getSymbolValue(symbol);
      }
      public String getSymbol() {
        return symbol;
      }
      public String getName() {
        return name;
      }
      public String getPrice() {
        return price;
      }
      private void getSymbolValue(String symbol) {
        String urlString =
        "http://quote.yahoo.com/download/javasoft.beans?SYMBOLS=" +
        symbol + "&format=nl";
      try {
        URL url = new URL(urlString);
        URLConnection con = url.openConnection();
        InputStream is = con.getInputStream();
        InputStreamReader isr = new InputStreamReader(is);
        BufferedReader br = new BufferedReader(isr);
        String line = br.readLine();
        StringTokenizer tokenizer = new StringTokenizer(line,",");
        name = tokenizer.nextToken();
        name = name.substring(1, name.length()-2); // remove quotes
        price = tokenizer.nextToken();
        price = price.substring(1, price.length()-2); // remove quotes
      } catch (IOException exception) {
        System.err.println("IOException: " + exception);
      }
     }
    }

     

    Once you've created the two JSP files, as well as created the JavaBean source file and compiled it, you can load up the quote.jsp file to see the results from http://localhost:8080/quote.jsp, assuming you haven't changed the JSWDK installation to use a different port. The page can definitely be prettied up, but it does what it needs to do functionally and is a good demonstration of JSP's capabilities.


     

    May 27

    开不了口

     周杰伦《开不了口》
    才离开没多久就开始 担心今天的你过得好不好
    整个画面是你 想你想得睡不着
    嘴嘟嘟那可爱的模样 还有在你身上香香的味道
    我的快乐是你想你想得都会笑
    没有你在我有多难熬[没有你在我有多难熬多烦恼]
    没有你烦我有多烦恼[没有你烦我有多烦恼多难熬]
    穿过云层 我试着努力向你奔跑
    爱才送到 你却已在别人怀抱
    就是开不了口让她知道 我一定会呵护着你也逗你笑
    你对我有多重要我后悔没让你知道
    安静的听你撒娇看你睡着一直到老
    就是开不了口让她知道 就是那么简单几句我办不到
    整颗心悬在半空 我只能够远远看着
    这些我都做得到 但那个人已经不是我じ★ve
    -------The End-------
      

     
    Photo 1 of 13
    by 
    by