Friday, January 18, 2013

Command Line Options for Java Garbage Collection Tuning


In my last blog entry I gave a simple overview of how GC or garbage collection works in Java. In this post i list some of the command line options which i found very useful for GC tuning and performance measurement.


Command   Details


-verbose:gc   Prints information at every collection

-XX:+PrintGCDetails

Prints detailed info of GC

-XX:+PrintGCTimeStamps


Will additionally print a time stamp at the start of each collection
-XX:MinHeapFreeRatio=<minimum>  


If the percent of free space in a generation falls below <minimum>% the size of the generation will be expanded so as to have <minimum>% of the space free assuming the size of the generation has not already reached its limit.

-XX:MaxHeapFreeRatio=<maximum>

If the percent of free space exceeds <maximum>% the size of the generation will be shrunk so as to have only <maximum>% of the space free as long as shrinking the generation does not decrease it below the minimum size of the generation.

-XX:NewRatio=ratioValue  

The young generation size is controlled by NewRatio. For example setting -XX:NewRatio=3 means that the ratio between the young and tenured generation is 1:3.

-XX:NewSize

Determines the lower limit of young gen size

-XX:MaxNewSize  

Determines the uppper limit of young gen size

-XX:SurvivorRatio=ratioValue

Sets the ratio between each survivor space and eden to be 1:ratioValue. Each survivor space will be 1/(ratioValue+2) of the young generation (as there are two survivor spaces).

-XX:+PrintTenuringDistribution

Can be used to show this threshold and the ages of objects in the new generation.

-XX:ParallelGCThreads=<desired number>

Determines the number of threads dedicated to Parallel GC.

-XX:MaxGCPauseMillis=<nnn>  

Determines the maximum pause time for GC

-XX:GCTimeRatio=<nnn>  

Sets the ratio of garbage collection time to application time to 1 / (1 + <nnn>) For example -XX:GCTimeRatio=19 sets a goal of 5% of the total time for garbage collection. By default the goal for total time for garbage collection is 1%.

-XX:YoungGenerationSizeIncrement=<nnn >  

Grows the size of young generation by nnn percent.

-XX:TenuredGenerationSizeIncrement=<nnn>  

Grows the size of tenured generation by nnn percent.

-XX:MaxPermSize=<desired size>  

Sets uppper limit of permanent gen size

-XX:+ TraceClassloading  

Know what classes are being loaded  

-XX:+ TraceClassUnloading  

Know what classes are being unloaded

-XX:MaxTenuringThreshold=n  To move an object that survives a young generation collection n times to the tenured generation. Note that the throughput collector does not use the MaxTenuringThreshold parameter.

-XX:+ DisableExplicitGC  

Disable explicit GC

-XX:CMSInitiatingOccupancyFraction=<percent>

The command line flag CMS Initiating Occupancy Fraction can be used to set the level at which the collection is started.


References: same as last blog entry on gc.

Sunday, January 13, 2013

Java garbage collection, generations and collectors

A "garbage collector" is the memory management system that gets rid of the objects that don't have any reference (dead object), make sure objects with reference (live object) are not removed and allocates memory space to new objects. this discussion focuses on the garbage collection in java. The discussion includes generation division of memory and different garbage collection strategies for them available in java.


Generation 
You either die young or you live long enough to see yourself become old generation!!

In generational collection the whole memory space is divided into divisions (generations) and different algorithm is used for garbage collection on each generation depending on the special characteristics of that generation.

For java the generations are divided according to the longevity of the survival of objects. it has two main generations. the young generation and the old generation. as the name suggests, newly created objects are stuffed into young generation. if the object survives long enough (enough number of garbage collection cycle) then its promoted to old generation.

Young generation is smaller and goes through frequent garbage collection. the hypothesis here is that most object die young. so whenever the tiny young generation is filled up a garbage collection runs on that part of memory (also referred to as a minor collection) and as a result dead objects are collected and removed, at the same time live objects which have survived enough number of garbage collection cycle are moved to the old generation.

Objects that are promoted to old generation are assumed to be living longer (as they have already faced enough garbage collector zombie waves and still survived the horror!!) and as a result garbage collection on old generation are a lot less frequent. When the old fills up a full collection (referred to as a major collection) is typically done on both young and old generations.

Just from a little common sense we can conclude that young generation garbage collection will need collection algorithm which are fast and with least pauses  (as it runs frequently) and old generation garbage collection needs to be space efficient (as old gen is a lot bigger than young gen). that being said lets go through some garbage collection algorithms available in java.


Serial Collection Strategy 

As the name suggests, garbage collection is done serially, one at a time. during this the whole application (for which garbage collection is done) is paused temporarily which is also referred as stop the world strategy.

For young gen it simply collects garbage serially and promotes objects if they are old enough. for old generation its a bit different. first an iteration is done over the whole old gen and dead objects are marked. the next iteration removes (sweeps) the dead ones. and in the end the live objects are moved closely next to each other (mostly to make them comfortable and warm and oddly but certainly) to keep the continuous free space in old gen as  big as possible. its called "mark-sweep-compact" -ing.  


Parallel Collection Strategy

Again the name suggests it all. Garbage collection is done with multiple CPUs simultaneously. Its also known as "throughput collector" (life is all about fancy names).

For young generation, it actually runs multiple serial collection using multiple CPUs  and thats it. For old gen, it does multiple serial "mark-sweep-compact"-ing thingy mentioned before using multiple CPUs simultaneously.

If you have enough money to afford multiple CPUs and a lot of memory then you are most probably gonna use it (but of course you might have the virtuous tendency to defy common practice). Also as both here are of the "stop the world" genre, you should think about time constraints as well.

Note:  the parallel collector can be set using the -XX:+UseParallelGC command line option.


Parallel Compacting Collection Strategy

This one is the improvement over "Parallel Collection Strategy". its mainly created to improve the parallel garbage collection in old generation part. the young generation part of it is same as "Parallel Collection Strategy".

Here the old gen is divided into same sized regions. each region gets its own garbage collection thread. (But that's just the tip of the iceberg but we will try to remain simple village folk here). in brief, before any collection, first a summary is generated for each region. from left to right, its looks for a region from where on all the regions are very lightly populated (so that the expense for compacting gets low). Left to that region nothing is done. And right to that region, collecting and compacting is done.

Nonetheless this strategy is of "stop-the-world" genre as well.

Note: the parallel compacting collector can be set using the -XX:+UseParallelOldGC command line option. 


Concurrent Mark-Sweep (CMS) Collection Strategy

For the young gen its the same as "Parallel Collection" (you can see how the young are neglected these days). But the magic starts with old gen collection. The following six phases of CMS are copied from oracle site, and i found them too fit for any alteration,

There are six phases involved in the collection:

Phase 1 (Initial Checkpoint) involves stopping all the Java threads, marking all the objects directly reachable from the roots, and restarting the Java threads.

Phase 2 (Concurrent Marking) starts scanning from marked objects and transitively marks all objects reachable from the roots. The mutators are executing during the concurrent phases 2, 3, and 5 below and any objects allocated in the CMS generation during these phases (including promoted objects) are immediately marked as live.

Phase 3: During the concurrent marking phase mutators may be modifying objects. Any object that has been modified since the start of the concurrent marking phase (and which was not subsequently scanned during that phase) must be rescanned. Phase 3 (Concurrent Precleaning) scans objects that have been modified concurrently. Due to continuing mutator activity the scanning for modified cards may be done multiple times.

Phase 4 (Final Checkpoint) is a stop-the-world phase. With mutators stopped the final marking is done by scanning objects reachable from the roots and by scanning any modified objects. Note that after this phase there may be objects that have been marked but are no longer live. Such objects will survive the current collection but will be collected on the next collection.

Phase 5 (Concurrent Sweep) collects dead objects. The collection of a dead object adds the space for the object to a free list for later allocation. Coalescing of dead objects may occur at this point. Note that live objects are not moved.

Phase 6 (Resetting) clears data structures in preparation for the next collection.

(I start again) Here the Stop the world pauses in phase 1 and 4 are very small. You might have noticed CMS  doesn't do any compacting. though its time saving, the free space isn't contiguous anymore. so next time the next object cant be just put beside last object and the expense for allocation gets increased. Also uneven fragments are created. to deal with fragmentation problems, popular object size is determined and for future demand. Moreover some dead object might miss the marking (if they die just after the marker passed over them) and cause "floating garbage" (as if we didn't have enough junk already).

Special Note: Unlike other collectors CMS starts old gen collection even before it gets full.  CMS
collector starts at a time based on statistics regarding previous collection times. It can also start based on what percentage of old gen is occupied, if you set –XX:CMSInitiatingOccupancyFraction = n (n is the value indicating percentage) , in command line options. The CMS collector can be set using the -XX:+UseConcMarkSweepGC command line option.  
In summary, compared to the parallel collector, the CMS collector decreases old generation pauses—sometimes dramatically—at the expense of slightly longer young generation pauses, some reduction in throughput, and extra heap size requirements.

I think thats big enough for one blog entry. other parts of GC such as selection criteria for collector, searching for memory leaks, heap profiling, throughput, tuning etc will be discussed later.

See command line options for tuning and performance analyzing of GC here.

References:



  









Saturday, January 12, 2013

short notes on how java garbage collection works (for my personal use)


this is just an extract from my research (?) on java garbage collection. contains discrete and unorganized notes.
these are mostly from


http://www.oracle.com/technetwork/java/gc-tuning-5-138395.html#1.1.%20Generations|outline
https://book.dynatrace.com/content/memory/reduce-garbage-collection-pause-time.aspx
http://chaoticjava.com/posts/how-does-garbage-collection-work/
http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html



-verbose:gc prints information at every collection
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps will additionally print a time stamp at the start of each collection


collections occur when generations fill up, throughput is inversely proportional to the amount of memory available. Total available memory is the most important factor affecting garbage collection performance.

-XX:MinHeapFreeRatio=<minimum>
-XX:MaxHeapFreeRatio=<maximum>

With these parameters if the percent of free space in a generation falls below <minimum>%, the size of the generation will be expanded so as to have <minimum>% of the space free, assuming the size of the generation has not already reached its limit.

Similarly, if the percent of free space exceeds <maximum>%, the size of the generation will be shrunk so as to have only <maximum>% of the space free as long as shrinking the generation does not decrease it below the minimum size of the generation.

the young generation size is controlled by NewRatio. For example, setting
-XX:NewRatio=3 means that the ratio between the young and tenured generation is 1:3.

The parameters NewSize and MaxNewSize bound the young generation size from below and above. Setting these equal to one another fixes the young generation, just as setting -Xms and -Xmx equal fixes the total heap size.

When there isn't enough memory available in the tenured generation for this worst case, a major collection will occur instead.

-XX:SurvivorRatio=6 sets the ratio between each survivor space and eden to be 1:6. In other words, each survivor space will be one eighth of the young generation (not one seventh, because there are two survivor spaces).

If survivor spaces are too small, copying collection overflows directly into the tenured generation. If survivor spaces are too large, they will be uselessly empty. At each garbage collection the virtual machine chooses a threshold number of times an object can be copied before it is tenured. This threshold is chosen to keep the survivors half full.

-XX:+PrintTenuringDistribution, can be used to show this threshold and the ages of objects in the new generation.

The discussion to this point has been about the serial collector.


The throughput collector: this collector uses a parallel version of the young generation collector. It is used if the -XX:+UseParallelGC option is passed on the command line. The tenured generation collector is the same as the serial collector.

The concurrent low pause collector: this collector is used if the -Xincgc ™ or -XX:+UseConcMarkSweepGC is passed on the command line. The concurrent collector is used to collect the tenured generation and does most of the collection concurrently with the execution of the application. The application is paused for short periods during the collection. A parallel version of the young generation copying collector is used with the concurrent collector.

Note that -XX:+UseParallelGC should not be used with -XX:+UseConcMarkSweepGC

throughput collector ->

Use the throughput collector when you want to improve the performance of your application with larger numbers of processors. The throughput collector is a generational collector similar to the serial collector but with multiple threads used to do the minor collection. The major collections are essentially the same as with the serial collector.

-XX:ParallelGCThreads=<desired number>
The maximum pause time goals is specified with the command line flag
-XX:MaxGCPauseMillis=<nnn>

-XX:GCTimeRatio=<nnn>

The ratio of garbage collection time to application time is

1 / (1 + <nnn>)
For example -XX:GCTimeRatio=19 sets a goal of 5% of the total time for garbage collection. By default the goal for total time for garbage collection is 1%.

Growing and shrinking the size of a generation is done by increments that are a fixed percentage of the size of the generation. By default a generation grows in increments of 20% and shrinks in increments of 5%.

The percentage for growing is controlled by the command line flag -XX:YoungGenerationSizeIncrement=<nnn > for the young generation and -XX:TenuredGenerationSizeIncrement=<nnn>

The throughput collector will throw an out-of-memory exception if too much time is being spent doing garbage collection.


concurrent low pause collector ->

Use the concurrent low pause collector if your application would benefit from shorter garbage collector pauses and can afford to share processor resources with the garbage collector when the application is running.

The concurrent low pause collector is a generational collector similar to the serial collector. The tenured generation is collected concurrently with this collector.

This collector attempts to reduce the pause times needed to collect the tenured generation. It uses a separate garbage collector thread to do parts of the major collection concurrently with the applications threads.



If the garbage collector has become a bottleneck, you may wish to customize the generation sizes.

Unless you have problems with pauses, try granting as much memory as possible to the virtual machine. The default size (64MB) is often too small.

Setting -Xms and -Xmx to the same value increases predictability by removing the most important sizing decision from the virtual machine. On the other hand, the virtual machine can't compensate if you make a poor choice.

Be sure to increase the memory as you increase the number of processors, since allocation can be parallelized.


The rules of thumb for server applications are:

First decide the total amount of memory you can afford to give the virtual machine. Then graph your own performance metric against young generation sizes to find the best setting.

Unless you find problems with excessive major collection or pause times, grant plenty of memory to the young generation.

Increasing the young generation becomes counterproductive at half the total heap or less (whenever the young generation guarantee cannot be met).

Be sure to increase the young generation as you increase the number of processors, since allocation can be parallelized.


How can I increase the permanent generation size?

Use the command line option -XX:MaxPermSize=<desired size>


    How do I know what classes are being loaded or unloaded?


Use the command line options -XX:+ TraceClassloading and -XX:+ TraceClassUnloading



Use the -XX option MaxTenuringThreshold to determine the copying costs. Use -XX:MaxTenuringThreshold=0 to move an object that survives a young generation collection immediately to the tenured generation. Note that the throughput collector does not use the MaxTenuringThreshold parameter.

The Concurrent Mark Sweep (CMS) collector (also referred to as the concurrent low pause collector) collects the tenured generation. It attempts to minimize the pauses due to garbage collection by doing most of the garbage collection work concurrently with the application threads.

Normally the concurrent low pause collector does not copy nor compact the live objects. A garbage collection is done without moving the live objects.f fragmentation in the tenured generation becomes a problem, a compaction of the tenured generation will be done although not concurrently. In 1.4.1 that compaction will occur if the UseCMSCompactAtFullCollection option is turned on.

-XX:+UseCMSCompactAtFullCollection

What are the phases of the concurrent low pause collector?


There are six phases involved in the collection:


Phase 1 (Initial Checkpoint) involves stopping all the Java threads, marking all the objects directly reachable from the roots, and restarting the Java threads.


Phase 2 (Concurrent Marking) starts scanning from marked objects and transitively marks all objects reachable from the roots. The mutators are executing during the concurrent phases 2, 3, and 5 below and any objects allocated in the CMS generation during these phases (including promoted objects) are immediately marked as live.


Phase 3: During the concurrent marking phase mutators may be modifying objects. Any object that has been modified since the start of the concurrent marking phase (and which was not subsequently scanned during that phase) must be rescanned. Phase 3 (Concurrent Precleaning) scans objects that have been modified concurrently. Due to continuing mutator activity the scanning for modified cards may be done multiple times.


Phase 4 (Final Checkpoint) is a stop-the-world phase. With mutators stopped the final marking is done by scanning objects reachable from the roots and by scanning any modified objects. Note that after this phase there may be objects that have been marked but are no longer live. Such objects will survive the current collection but will be collected on the next collection.

Phase 5 (Concurrent Sweep) collects dead objects. The collection of a dead object adds the space for the object to a free list for later allocation. Coalescing of dead objects may occur at this point. Note that live objects are not moved.

Phase 6 (Resetting) clears data structures in preparation for the next collection.


What is the Parallel Young Generation collector (-XX:+UseParNewGC)?


The parallel young generation collector is similar to the parallel garbage collector (-XX:+UseParallelGC) in intent and differs in implementation. Most of the above description for the parallel garbage collector (-XX:+UseParallelGC) therefore applies equally for the parallel young generation collector. Unlike the parallel garbage collector (-XX:+UseParallelGC) this parallel young generation collector can be used with the concurrent low pause collector that collects the tenured generation.


If you're using RMI (remote method invocation), then you could be running into distributed garbage collection (GC). Also, some applications are adding explicit GC's thinking that it will make their application faster. Luckily, you can disable this with an option available in version 1.3 and 1.4. Try -XX:+ DisableExplicitGC along with -verbose:gc and see if this helps.


A concurrent collection starts running when the percentage of allocated space in the old generation crosses a threshold. This threshold is calculated based on general experience with the concurrent collector. If full collections are occurring, the concurrent collections may need to be started earlier. The command line flag CMSInitiatingOccupancyFraction can be used to set the level at which the collection is started. Its default value is approximately 68%. The command line to adjust the value is

-XX:CMSInitiatingOccupancyFraction=<percent>





What are the default settings for the concurrent low pause collector?

The default heap size for the concurrent low pause collector is the same as for the default collector. The other parameters are set a described below. These setting have been shown to work well for an application that has mostly very short lived data plus some data that is very long lived. Some of the options require a computation which is enclosed in angle brackets (<>), of which two depend on the number of cpus on the machine (#cpus.)

# enable the concurrent low pause collector

-XX:+UseConcMarkSweepGC



# use parallel threads

-XX:+UseParNewGC

-XX:ParallelGCThreads=<#cpus < 8 ? #cpus : 3 + ((5 * #cpus) / 8) >

-XX:+CMSParallelRemarkEnabled



# size young generation for short pauses

-XX:NewSize=4m

-XX:MaxNewSize=< 4m * ParallelGCThreads >



# promote all live young generation objects

-XX: MaxTenuringThreshold=0

-XX:SurvivorRatio=1024


It is also recommended that a heap size be used that is 20-30% larger than that which would be used with the default collector.



[GC [<collector>: <starting occupancy1> -> <ending occupancy1>, <pause time1> secs] <starting occupancy3> -> <ending occupancy3>, <pause time3> secs]


where

<collector> is an internal name for the collector used in the minor collection

<starting occupancy1> is the occupancy of the young generation before the collection

<ending occupancy1> is the occupancy of the young generation after the collection

<pause time1> is the pause time in seconds for the minor collection.

<starting occupancy3> is the occupancy of the entire heap before the collection

<ending occupancy3> is the occupancy of the entire heap after the collection

<pause time3> is the pause time for the entire garbage collection. This would include the time for a major collection is one was done.


http://www.oracle.com/technetwork/java/gc-tuning-5-138395.html#1.1.%20Generations|outline
https://book.dynatrace.com/content/memory/reduce-garbage-collection-pause-time.aspx

Friday, January 4, 2013

CRUD operation on weblogic embedded ldap using spring ldapTemplate, jsf and CDI

here i created a java ee 6 based web application to perform CRUD operation on weblogic embedded ldap. JSF 2.0 and Spring ldapTemplate has been used.

the applicationContext.xml is the same as described in my previous post on weblogic embedded ldap. injection of Spring ldapTemplate via CDI is also similar to that post.

lets look at the codes as they speak a lot more than normal explanation,

the model person is a simple pojo

 package model;  
   
 import java.io.Serializable;  
 import javax.inject.Named;  
 import javax.validation.constraints.Size;  
 import org.hibernate.validator.constraints.NotEmpty;  
  
 /**  
  * @author nayef  
  */  
   
 @Named  
 public class Person implements Serializable {  
     
   @NotEmpty(message = "the uid cant be empty")    
   private String uid;  
     
   @NotEmpty(message = "full name cant be empty")  
   @Size(max =20, min =5, message="you must provide a full name between 5 to 20 characters")  
   private String fullName;  
     
   @NotEmpty(message = "short name cant be empty")  
   @Size(max =10, min =3, message="you must provide a short name between 3 to 10 characters")  
   private String shortName;  
   
   @NotEmpty(message = "the password cant be empty")  
   private String password;  
   
   public String getFullName() {  
     return fullName;  
   }  
   
   public void setFullName(String fullName) {  
     this.fullName = fullName;  
   }  
   
   public String getPassword() {  
     return password;  
   }  
   
   public void setPassword(String password) {  
     this.password = password;  
   }  
   
   public String getShortName() {  
     return shortName;  
   }  
   
   public void setShortName(String shortName) {  
     this.shortName = shortName;  
   }  
   
   public String getUid() {  
     return uid;  
   }  
   
   public void setUid(String uid) {  
     this.uid = uid;  
   }  
   
   @Override  
   public String toString() {  
     return "Person{" + "uid=" + uid + ", fullName=" + fullName + ", shortName=" + shortName + '}';  
   }  
  
 } 


the index page contains links of all the other pages,

   
 <?xml version='1.0' encoding='UTF-8' ?>  
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
 <html xmlns="http://www.w3.org/1999/xhtml"  
    xmlns:h="http://java.sun.com/jsf/html">  
   <h:head>  
     <title>starting page</title>  
   </h:head>  
   <h:body>  
      to create  go to <h:link value="create page" outcome="create" />  
     <br/>  
     to search  go to <h:link value="search page" outcome="search" />  
     <br/>  
     for list  go to <h:link value="list page" outcome="list" />  
   </h:body>  
 </html>  
   


the create.xhtml contains a simple form to create

   
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"  
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
 <html xmlns="http://www.w3.org/1999/xhtml"  
    xmlns:h="http://java.sun.com/jsf/html">  
   
   <head>  
     <title>create person</title>  
   </head>  
   <body>  
     <h:form>  
       <h:outputLabel value="Enter UID " />  
       <h:inputText value="#{personController.person.uid}" />  
   
       <br/>  
   
       <h:outputLabel value="Enter Full Name" />  
       <h:inputText value="#{personController.person.fullName}" />  
   
       <br />  
   
       <h:outputLabel value="Enter short Name" />  
       <h:inputText value="#{personController.person.shortName}" />  
   
       <br/>  
   
       <h:outputLabel value="Enter password" />  
       <h:inputSecret value="#{personController.person.password}" />  
   
       <br/>  
   
       <h:commandButton value="Create" action="#{personController.createPerson}" />  
       <h:commandButton value="Cancel" action="#{personController.cancel}" immediate="true"/>  
   
     </h:form>  
   
     <br/>  
     start page <h:link value="start page" outcome="index" />  
     <br/>  
      
   </body>  
 </html>  


the modify.xhtml is like the following. it contains both options for update and delete.

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"  
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
 <html xmlns="http://www.w3.org/1999/xhtml"  
    xmlns:h="http://java.sun.com/jsf/html">  
   
   <head>  
     <title>modify person</title>  
   </head>  
   <body>  
     <h:form id="modifyForm">  
       <h:outputLabel value="Enter UID " />  
       <h:outputText value="#{personController.person.uid}" />  
   
       <br/>  
   
       <h:outputLabel value="Enter Full Name" />  
       <h:inputText value="#{personController.person.fullName}" />  
   
       <br />  
   
       <h:outputLabel value="Enter short Name" />  
       <h:inputText value="#{personController.person.shortName}" />  
   
       <br />  
       <br/>  
   
       <h:outputLabel value="previous password" />  
       <h:inputSecret id="previousPassword" validator="#{personController.passwordValidator}" required="true">  
           
       </h:inputSecret>  
         
       <br/>  
   
       <h:outputLabel value="Enter password" />  
       <h:inputSecret value="#{personController.person.password}" />  
   
       <br/>  
   
       <h:commandButton value="Modify" action="#{personController.updatePerson}" />  
       <br/>  
       <h:commandButton value="Delete" action="#{personController.deletePerson}" immediate="true"/>  
         
       <br/>  
       <h:commandButton value="Cancel" action="#{personController.cancel}" immediate="true"/>  
   
     </h:form>  
       
   </body>  
 </html>  


the list.xhtml lists all the entries and gives option to load entries for modification

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"  
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
 <html xmlns="http://www.w3.org/1999/xhtml"  
    xmlns:h="http://java.sun.com/jsf/html">  
   <head>  
     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>  
     <title>person list</title>  
   </head>  
   <body>  
     <h:form>  
       <h:dataTable value="#{personController.personList}" var="personElement">  
         <h:column>  
           #{personElement.uid}  
         </h:column>  
         <br/>  
         <h:column>  
           #{personElement.fullName}  
         </h:column>  
         <br/>  
         <h:column>  
           #{personElement.shortName}  
         </h:column>  
         <br/>  
         <h:column>  
   
           <h:commandLink action="#{personController.loadPersonFromList(personElement.uid)}" value="load">  
   
           </h:commandLink>  
         </h:column>  
   
       </h:dataTable>  
     </h:form>  
     <br/>  
     to create  go to <h:link value="create page" outcome="create" />  
     <br/>  
     start page <h:link value="start page" outcome="index" />  
   </body>  
 </html>  
   


the search.xhtml lets you search entries using uid.

   
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"  
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
 <html xmlns="http://www.w3.org/1999/xhtml"  
    xmlns:h="http://java.sun.com/jsf/html">  
   <head>  
     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>  
     <title>Search</title>  
   </head>  
   <body>  
  <h:form>  
   <h:outputLabel value="Enter your uid" />  
   <h:inputText value="#{personController.searchUid}" />  
   
   
   <h:commandButton value="Submit"  
            action="#{personController.loadPerson}" />  
 </h:form>  
     <br/>  
     start page <h:link value="start page" outcome="index" />  
   </body>  
 </html>  
   


failure notification page,

   
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"  
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
 <html xmlns="http://www.w3.org/1999/xhtml"  
    xmlns:h="http://java.sun.com/jsf/html"  
    xmlns:f="http://java.sun.com/jsf/core">  
     
   <head>  
     <title>failed</title>  
   </head>  
   <body>  
     <h1>failed</h1>  
      <br/>  
     start page <h:link value="start page" outcome="index" />  
   </body>  
 </html>  
   
the controller for this CRUD operation is as follows,
package Controller;

import Dao.PersonDaoImpl;
import java.io.Serializable;
import java.util.List;
import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.ValidatorException;
import javax.inject.Inject;
import javax.inject.Named;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import model.Person;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.filter.AndFilter;
import org.springframework.ldap.filter.EqualsFilter;

/**   
 *   
 * @author nayef   
 */
@Named
@ConversationScoped
public class PersonController implements Serializable {

    @Valid
    @NotNull
    private Person person = new Person();
    @NotNull
    String searchUid;
    @Inject
    private PersonDaoImpl dao;
    @Inject
    private Conversation conversation;
    @Inject
    private LdapTemplate ldapTemplate;

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }

    public String getSearchUid() {
        return searchUid;
    }

    public void setSearchUid(String searchUid) {
        this.searchUid = searchUid;
    }

    public LdapTemplate getLdapTemplate() {
        return ldapTemplate;
    }

    public void setLdapTemplate(LdapTemplate ldapTemplate) {
        this.ldapTemplate = ldapTemplate;
    }

    public List<Person> getPersonList() {

        List<Person> personList = dao.findAll();

        return personList;
    }

    public String createPerson() {

        try {
            dao.create(person);
        } catch (Exception e) {
            return "actionFailed?faces-redirect=true";
        }

        return "list?faces-redirect=true";

    }

    public String loadPerson() {

        beginConversation();

        try {
            Person tempPerson = dao.findPersonByUid(searchUid);
            this.person = tempPerson;

        } catch (Exception e) {

            endConversation();
            if (e instanceof org.springframework.ldap.NameNotFoundException) {
            } else {
                System.out.println(e.toString());
            }

            return "actionFailed?faces-redirect=true";
        }

        return "modify?faces-redirect=true";
    }

    public String updatePerson() {
        try {
            dao.updatePersonByUid(this.getPerson());
        } catch (Exception e) {
            endConversation();
            return "actionFailed?faces-redirect=true";
        }

        endConversation();
        return "list?faces-redirect=true";
    }

    public String loadPersonFromList(String uid) {

        beginConversation();
        try {
            Person tempPerson = dao.findPersonByUid(uid);
            this.person = tempPerson;

        } catch (Exception e) {
            conversation.end();
            endConversation();
            return "actionFailed?faces-redirect=true";
        }

        return "modify?faces-redirect=true";

    }

    public String deletePerson() {
        try {
            dao.deletePersonByUid(this.getPerson());
        } catch (Exception e) {
            endConversation();
            return "actionFailed?faces-redirect=true";
        }

        endConversation();
        return "list?faces-redirect=true";
    }

    public String loadPersonList() {
        endConversation();
        return "list?faces-redirect=true";

    }

    public String cancel() {
        endConversation();
        return "index?faces-redirect=true";
    }

    public void passwordValidator(FacesContext context, UIComponent toValidate, Object value) {

        String uid = this.getPerson().getUid();
        String password = (String) value;
        if (password == null || password.trim().length() < 1) {
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    "previous Password cant be empty", "previous Password cant be empty");
            throw new ValidatorException(message);
        }
        if (!loginExistsInLdap(uid, password.trim())) {
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    "previous password not correct", "previous password not correct");
            throw new ValidatorException(message);
        }
    }

    public boolean loginExistsInLdap(String uid, String password) {
        AndFilter filter = new AndFilter();
        filter.and(new EqualsFilter("objectclass", "person")).and(new EqualsFilter("uid", uid));
        boolean legit = false;

        try {
            legit = this.ldapTemplate.authenticate(DistinguishedName.EMPTY_PATH, filter.toString(), password);
        } catch (Exception e) {
            legit = false;
        }

        return legit;

    }

    private void beginConversation() {
        if (conversation.isTransient()) {
            conversation.begin();
        }
    }

    private void endConversation() {
        if (!conversation.isTransient()) {
            conversation.end();
        }
    }
}



the dao layer is like this

package Dao;

import java.util.List;
import model.Person;

/**
 *
 * @author nayef
 */
public interface PersonDao {

    public void create(Person p);

    public void updatePersonByUid(Person p);

    public void delete(Person p);

    public Person findPersonByUid(String uid);

    public List<Person> findAll();
}



dao layer implementation uses spring LdapTemplate for ldap operations


package Dao;

import java.io.Serializable;
import java.util.List;
import javax.inject.Inject;
import javax.naming.Name;
import model.Person;
import org.springframework.ldap.core.ContextMapper;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.filter.EqualsFilter;

/**
 *
 * @author nayef
 */
public class PersonDaoImpl implements PersonDao, Serializable {

    @Inject
    private LdapTemplate ldapTemplate;

    public void setLdapTemplate(LdapTemplate l) {
        ldapTemplate = l;
    }

    @Override
    public void create(Person p) {
        DirContextAdapter context = new DirContextAdapter();
        mapToContext(p, context);
        ldapTemplate.bind(buildDn(p), context, null);
    }

    @Override
    public void delete(Person p) {
        ldapTemplate.unbind(buildDn(p));
    }

    @Override
    public List<person> findAll() {
        EqualsFilter filter = new EqualsFilter(
                "objectclass", "person");
        return ldapTemplate.search(
                DistinguishedName.EMPTY_PATH,
                filter.encode(), getContextMapper());
    }

    @Override
    public void updatePersonByUid(Person person) {
        DistinguishedName dn = new DistinguishedName();
        dn.add("ou", "people");
        dn.add("uid", person.getUid());

        DirContextAdapter context = (DirContextAdapter) ldapTemplate.lookup(dn);
        mapToContext(person, context);
        ldapTemplate.modifyAttributes(dn, context.getModificationItems());
    }

    @Override
    public Person findPersonByUid(String uid) {
        DistinguishedName dn = new DistinguishedName();
        dn.add("ou", "people");
        dn.add("uid", uid);
        return (Person) ldapTemplate.lookup(dn, getContextMapper());
    }

    public void deletePersonByUid(Person person) {
        DistinguishedName dn = new DistinguishedName();
        dn.add("ou", "people");
        dn.add("uid", person.getUid());
        ldapTemplate.unbind(dn);
    }

    protected ContextMapper getContextMapper() {
        return new PersonContextMapper();
    }

    protected Name buildDn(Person p) {
        DistinguishedName dn = new DistinguishedName();

        dn.add("ou", "people");
        dn.add("uid", p.getUid());
        return dn;
    }

    protected void mapToContext(Person p, DirContextAdapter context) {
        context.setAttributeValues("objectclass", new String[]{"top",
                    "person", "inetOrgPerson", "organizationalPerson", "wlsuser"});
        context.setAttributeValue("cn", p.getFullName());
        context.setAttributeValue("sn", p.getShortName());
        context.setAttributeValue("uid", p.getUid());
        context.setAttributeValue("userPassword", p.getPassword());


    }

    private static class PersonContextMapper implements ContextMapper {

        @Override
        public Object mapFromContext(Object ctx) {
            DirContextAdapter context = (DirContextAdapter) ctx;
            Person p = new Person();
            p.setFullName(context.getStringAttribute("cn"));
            p.setShortName(context.getStringAttribute("sn"));
            p.setUid(context.getStringAttribute("uid"));
            return p;
        }
    }
}



References

1. https://blogs.oracle.com/jamesbayer/entry/look_inside_weblogic_server_em
2. http://today.java.net/pub/a/today/2006/04/18/ldaptemplate-java-ldap-made-simple.html
3. http://www.jayway.com/2009/02/02/simple-authentication-using-spring-ldap/