| John TK's profilej0Hn:cH1n:7hA0:K3n9@w3bL...PhotosBlogLists | Help |
|
August 17 reverse proxyA 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:
Reverse proxy is, as the name suggests, similar to "proxying backwards". 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) 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.
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 ObjectsThe remoting infrastructure allows you to create two distinct types of remote objects.
A Look At ASP.NET Web ServicesWith 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. 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. 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. 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. .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. .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. 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 deploymentIn 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 objectCreating 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; 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; 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" ?> 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 ServiceAs 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; 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 ServiceYou 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.
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 FidelityASP.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 togetherSo far, we have looked at the differences between these two technologies. Let us summarize the difference in a table.
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 ActionSo 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. ConclusionBoth 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.0EJB 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:
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 SolutionsJava/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.XAt 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.0With 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:
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 ToolsThere 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:
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 DirectorySendmail 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 patternsJ2EE 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 PatternsTable 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 PatternsTable 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 PatternsTable 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
Stateless session beans
Stateful session beans
Entity beans
Message driven beans
Tuning Entity beansThe 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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 EJBChoosing 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 :
Disadvantages :
2. HttpSession object Advantages:
Disadvantages:
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.
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
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.
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. 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
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!
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!
June 02 Best practices for closing ResultSet and CallableStatement within loopThe 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. 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 ....... ............. check_pfiles #!/usr/bin/sh while true check_lsof #!/usr/bin/sh while true
postprintSolaris 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.June 01 《棋子》 《棋子》 举棋不定 May 31 Using a Run Control Script to Stop or Start ServicesNote - 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.
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 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.
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 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.
The following example shows how to rename the S100datainit script. # cd /etc/rc2.d # mv S100datainit _S100datainit # ls _* # _S100datainit 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. http://docsun.cites.uiuc.edu/sun_docs/C/solaris_9/SUNWaadm/SYSADV1/p38.html Essential Elements for Any Successful ProjectWhat 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.
From a utopian, academic standpoint, the "ultimate" successful project would be defined as a project that:
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 Shutdownrc 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:
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 S99dtloginAs 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:
The /sbin/rcS script runs the /etc/rcS.d scripts to bring the system up to single-user mode and to do the following:
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:
The /sbin/rc2 script sets the TIMEZONE variable, runs the /etc/rc2.d scripts, and does the following:
The /sbin/rc3 script runs the /etc/rc3.d scripts and does the following:
The /sbin/rc5 and /sbin/rc6 scripts run the /etc/rc0.d scripts and do the following:
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 DirectoriesWhen 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
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/K100programYou can verify the links by typing this: # ls -li /etc/init.d/*program /etc/rc?.d/[SK]*programThe 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/S77programNOTE 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.
|
|
|