 |
June 2007 Archives
Extending the NetBeans Tutorial JSF-JPA-Hibernate Application, Part 3 - Enabling JMX Monitoring on Hibernate v3 and Ehcache 1.3.0 on "SimpleJpaHibernateApp"
Posted by maxpoon on June 27, 2007 at 11:21 AM | Permalink
| Comments (0)
Background
This is the continuation from the
previous article "Extending
the NetBeans Tutorial JSF-JPA-Hibernate Application, Part 2 - Enabling
JMX Monitoring on Hibernate v3 and Ehcache 1.3, on HibernateTutorialApp"
where we continue with (3) and (4) of the following :
- Configuring
HibernateTutorialApp/HibernateTravelPOJO to use Ehcache 1.3.0
- Configuring
HibernateTutorialApp/HibernateTravelPOJO to enable JMX monitoring on
Hibernate and Ehcache
- Configuring
SimpleJpaHibernateApp to use Ehcache 1.3.0
- Configuring
SimpleJpaHibernateApp to enable JMX monitoring on
Hibernate and Ehcache
(3)
Configuring
SimpleJpaHibernateApp to use Ehcache 1.3.0
The configurations for SimpleJpaHibernateApp, created
with the NetBeans tutorial "Using
Hibernate With the Java Persistence API", to use Ehcache 1.3.0 are
similar to those of "Configuring
HibernateTutorialApp/HibernateTravelPOJO to use Ehcache 1.3.0" ,
except :
- SimpleJpaHibernateApp is directly configured to use Hibernate
(Hibernate-3.2.2, or above, e.g.
Hibernate-3.2.4sp1) and Ehcache-1.3.0
- persistence.xml and hibernate.cfg.xml (cache
related configurations highlighted in bold), and ehcache.cfg.xml as shown :
| Code Listing 3.1 - persistence.xml for
SimpleJpaHibernateApp |
<?xml version="1.0"
encoding="UTF-8"?>
<persistence
version="1.0" xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit
name="SimpleJpaHibernateAppPU" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>jdbc/sample</jta-data-source>
<class>simpleJpaHibernateApp.entities.ProductCode</class>
<class>simpleJpaHibernateApp.entities.Product</class>
<class>simpleJpaHibernateApp.entities.Manufacturer</class>
<properties>
<property name=
"hibernate.ejb.classcache.simpleJpaHibernateApp.entities.ProductCode"
value="read-write"/>
<property name=
"hibernate.ejb.classcache.simpleJpaHibernateApp.entities.Product"
value="read-write"/>
<property name=
"hibernate.ejb.classcache.simpleJpaHibernateApp.entities.Manufacturer"
value="read-write"/>
<property name="hibernate.ejb.cfgfile"
value="/hibernate.cfg.xml"/>
</properties>
</persistence-unit>
</persistence> |
Code Listing 3.2 - hibernate.cfg.xml for
SimpleJpaHibernateApp
|
<?xml version='1.0'
encoding='utf-8'?>
<!DOCTYPE
hibernate-configuration PUBLIC
"-//Hibernate/Hibernate
Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!--
SQL dialect -->
<property name="hibernate.dialect">
org.hibernate.dialect.DerbyDialect</property>
<!--
Debug logging of SQL statements -->
<property name="hibernate.show_sql">true</property>
<!--
Cache Configurations -->
<!--
Using net.sf.ehcache.hibernate.SingletonEhCacheProvider instead of
net.sf.ehcache.hibernate.EhCacheProvider ensures the same instance
of CacheManager is referred to by
both Hibernate and our JMX Agent
simpleJpaHibernateApp.agents.jmxAgent. (Thanks to Greg Luck!)
-->
<property name="hibernate.cache.provider_class">
net.sf.ehcache.hibernate.SingletonEhCacheProvider</property>
<property name="hibernate.cache.provider_configuration">
/ehcache.cfg.xml</property>
<property
name="hibernate.cache.use_minimal_puts">false</property>
<property
name="hibernate.cache.use_query_cache">true</property>
<property
name="hibernate.cache.use_second_level_cache">true</property>
<property
name="hibernate.cache.use_structured_entries">true</property>
</session-factory>
</hibernate-configuration>
|
| Coding Listing 3.3 - ehcache.cfg.xml for
SimpleJpaHibernateApp |
<?xml version="1.0"
encoding="UTF-8"?>
<ehcache
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd">
<diskStore
path="java.io.tmpdir"/>
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
diskPersistent="true"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"
/>
<cache name="simpleJpaHibernateApp.entities.ProductCode"
maxElementsInMemory="300"
eternal="true"
overflowToDisk="false"
/>
<cache name="simpleJpaHibernateApp.entities.Product"
maxElementsInMemory="300"
eternal="true"
overflowToDisk="false"
/>
<cache name="simpleJpaHibernateApp.entities.Manufacturer"
maxElementsInMemory="300"
eternal="true"
overflowToDisk="false"
/>
<cache
name="simpleJpaHibernateApp.entities.ProductCode.productCollection"
maxElementsInMemory="300"
eternal="true"
overflowToDisk="false"
/>
<cache
name="simpleJpaHibernateApp.entities.Manufacturer.productCollection"
maxElementsInMemory="300"
eternal="true"
overflowToDisk="false"
/>
</ehcache>
|
(4)
Configuring SimpleJpaHibernateApp to enable JMX monitoring on
Hibernate and Ehcache
After being configured to use Ehcache 1.3.0 as shown in "Configuring
SimpleJpaHibernateApp to use Ehcache 1.3.0" above, the
SimpleJpaHibernateApp can also be extended to
enable JMX monitoring, e.g. on Hibernate and Ehcache used, similar to "Configuring
HibernateTutorialApp/HibernateTravelPOJO to enable JMX monitoring on
Hibernate and Ehcache" in previous article.
Step 4.1 - Create JMX Agent with Hibernate and Ehcache MBeans
Registration Codes
Similar to Step 2.1
in "Configuring
HibernateTutorialApp/HibernateTravelPOJO to enable JMX monitoring on
Hibernate and Ehcache", we need to create the JMX Agent which
registers the Hibernate
and Ehcache MBeans to enable JMX monitoring on them. However,
there are a few small but important differences here...
(A) To register Hibernate's MBean, we still need the following codes :
// Enable Hibernate JMX Statistics
StatisticsService statsMBean = new StatisticsService();
statsMBean.setSessionFactory(sessionFactory);
statsMBean.setStatisticsEnabled(true);
mbs.registerMBean(statsMBean, on);
i.e. we need to get Hibernate SessionFactory from our JPA
execution environment (which uses the implementation-independent JPA PersistentUnit and the associated EntityMangerFactory instead) to
enable JMX monitoring on Hibernate, by (also used by the NetBeans
Tutorial "NetBeans
Wiki - UsingHibernateWithJPA") :
- Session
session = (Session) em.getDelegate();
And, in our case for SimpleJpaHibernateApp, it is followed by :
- SessionFactory
sessionFactory = session.getSessionFactory();
to get SessionFactory as in Code Listing
4.1 (additional MBeans registration codes in bold) below.
(B) Also, we would like to modify the init() method to take EntityMangerFactory from the
calling context, to get the Hibernate SessionFactory for registering
Hibernate statsMBean.
Code Listing 4.1 - SimpleJpaHibernateApp's
JmxAgent.java
|
/*
* JmxAgent.java
*
*/
package
simpleJpaHibernateApp.agents;
import
java.lang.management.ManagementFactory;
import
javax.management.MBeanServer;
import
javax.management.ObjectName;
import
javax.persistence.EntityManagerFactory;
import
javax.persistence.EntityManager;
import
net.sf.ehcache.CacheManager;
import
net.sf.ehcache.management.ManagementService;
import
org.hibernate.Session;
import
org.hibernate.SessionFactory;
import
org.hibernate.jmx.StatisticsService;
/**
* JMX agent
(singleton) for monitoring Hibernate and Ehcache
* in
SimpleJpaHibernateApp, which uses:
* <ul>
*
<li>JavaServer Faces (JSF) web-tier</li>
* <li>Java
Persistence API (JPA) persistence</li>
* <li>Hibernate
Core (3.2.4 sp1) and Hibernate EntityManager (3.3.1)</li>
* <li>Ehcache
1.3.0</li>
* </ul>
*
* @author Max Poon
(maxpoon@dev.java.net)
*/
public class JmxAgent {
private
EntityManager em;
private
Session session;
private
SessionFactory sf;
/**
*
Instantiate, register MBeans, enable Hibernate & Ehcache JMX
Statistics
*
@param emf javax.persistence.EntityManagerFactory to be passed in
*
from the invoking context (instead of creating it here
*
which is expensive operation)
*/
public
void init(EntityManagerFactory
emf)
throws Exception {
try {
// Create EntityManager from EntityManagerFactory passed in
// from the invoking context
em = emf.createEntityManager();
// Get Hibernate Session and SessionFactory from EntityManager
// *Important* for registering the Hibernate SessionFactory
// with org.hibernate.jmx.StatisticsService later on
// to enable JMX monitoring of Hibernate statistics
session = (Session)
em.getDelegate();
sf = session.getSessionFactory();
} catch (Exception ex) {
ex.printStackTrace();
} finally {
em.close();
}
ObjectName on = new ObjectName
("Hibernate:type=statistics,application=SimpleJpaHibernateApp");
// Enable Hibernate JMX Statistics
StatisticsService statsMBean = new StatisticsService();
statsMBean.setSessionFactory(sf);
statsMBean.setStatisticsEnabled(true);
mbs.registerMBean(statsMBean, on);
/*
* Enable Ehcache JMX Statistics
*
Use CacheManager.getInstance() instead of new CacheManager()
* as net.sf.ehcache.hibernate.SingletonEhCacheProvider is used
* to ensure reference to the same CacheManager instance as used
* by Hibernate
*/
CacheManager cacheMgr = CacheManager.getInstance();
ManagementService.registerMBeans
(cacheMgr, mbs, true, true, true, true);
}
/**
*
Returns an agent singleton.
*/
public
synchronized static JmxAgent getDefault(EntityManagerFactory emf)
throws Exception {
if(singleton == null) {
singleton = new JmxAgent();
singleton.init(emf);
}
return singleton;
}
public
MBeanServer getMBeanServer() {
return mbs;
}
//
Platform MBeanServer used to register your MBeans
private
final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
//
Singleton instance
private
static JmxAgent singleton;
}
|
Step 4.2 Modify JSF Managed Beans to initiate JMX Agent
Unlike the HibernateTravelPOJO
application, there
is no HibernateUtil.java-like
object for getting Hibernate Session in
SimpleJpaHibernateApp. One solution is to initiate JmxAgent
during the 1st retrieval of EntityManager in following JSF
managed beans / controllers :
- simpleJpaHibernate.controllers.ProductController
- simpleJpaHibernate.controllers.ProductCodeController
- simpleJpaHibernate.controllers.ManufacturerController
e.g. as shown in Code Listing 4.2 for simpleJpaHibernate.controllers.ProductController
:
Code Listing 4.2 - ProductController.java
modified to initiate JmxAgent if needed
|
/*
*
ProductController.java
*
*/
package
simpleJpaHibernateApp.controller;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.annotation.Resource;
....
import
simpleJpaHibernateApp.agents.JmxAgent;
import
simpleJpaHibernateApp.entities.Manufacturer;
import
simpleJpaHibernateApp.entities.Product;
import
simpleJpaHibernateApp.entities.ProductCode;
/**
* This version of ProductController uses JPA query with SQL joint
* to retrieve all Products associated with a given ProductCode
* indicated by its ID 'selectedProdCode'.
* This shows simple code modification to get additional behaviour.
*
* @author Max Poon (maxpoon@dev.java.net)
*/
public class
ProductController {
/**
Creates a new instance of ProductController */
public
ProductController() { }
private
Product product;
private
ProductCode selectedProductCode;
private
String selectedProdCode;
private
DataModel model;
@Resource
private
UserTransaction utx;
@PersistenceUnit(unitName = "SimpleJpaHibernateAppPU")
private
EntityManagerFactory emf;
private
EntityManager getEntityManager() {
initJMX();
return emf.createEntityManager();
}
//
Initiate JMX if needed
void initJMX() {
try {
JmxAgent.getDefault(emf);
} catch (Exception ex) {
ex.printStackTrace();
}
}
...
...
|
Similar modifications should also be
done for :
- simpleJpaHibernate.controllers.ProductCodeController
- simpleJpaHibernate.controllers.ManufacturerController
Then recompile SimpleJpaHibernateApp
with the above configurations and checked that it is working fine
getting also the web interface and functionalities as those in "Extending
the NetBeans Tutorial JSF-JPA-Hibernate Application, Part 1 -
Co-ordinating Query Views Based on Parameter Passing from JSF View to
Managed Bean".
Step 4.3 - Use
JConsole to Observe JMX Statistics
Similar to Step 2.3 in "Configuring
HibernateTutorialApp/HibernateTravelPOJO to enable JMX monitoring on
Hibernate and Ehcache", start JConsole
and connect to JVM running GlassFish (indicated by
"com.sun.enterprise.server.PELaunch"
in JConsole) and observe the
following real-time JMX information collected.
Starting with the "Listing ProductCodes" page :
Figure
4.3.1 - "Listing ProductCodes" page of SimpleJpaHibernateApp
|

Figure
4.3.2 - JConsole showing Hibernate Entity Names, Queries, 2nd Level
Cache Regions, and related statistics
|

Figure 4.3.3 -
JConsole showing Ehcache Statistics on ProductCode, with 6 cache miss
for the 6 ProductCode instances retrieved
|

Click on "SW" page on "Listing ProductCodes" page to get the following,
then click on "List of Product with this Product Code" to get the next
screen shown in Figure
4.3.7.
Figure 4.3.4 - "Detail of ProductCode" page
of SimpleJpaHibernateApp for ProdCode="SW"
|

Figure
4.3.5 - JConsole showing Hibernate Statistics being updated as compared
to Figure
4.3.2
|

Figure 4.3.6 -
JConsole showing Ehcache Statistics for ProductCode updated (with 2
more cache misses and 7 more cache hits) as compared to Figure
4.3.3
|

| Figure 4.3.7 - "Listing
Products" page of SimpleJpaHibernateApp for ProdCode="SW" |

| Figure
4.3.8 - JConsole showing Hibernate
Statistics being updated as compared to Figure
4.3.5 |

| Figure
4.3.9 - JConsole showing Ehcache
Statistics for ProductCode updated, with 1 more (ProductCode where
ProdCode="SW") cache hit as compared to Figure
4.3.6 |

Figure
4.3.10 - JConsole showing Ehcache
Statistics for Product, with 8 new retrieval, i.e. cache misses, for
the 8 Product
instances where ProdCode="SW" as shown in Figure
4.3.7
|

Continue Reading...
Extending the NetBeans Tutorial JSF-JPA-Hibernate Application, Part 2 - Enabling JMX Monitoring on Hibernate v3 and Ehcache 1.3.0 on "HibernateTutorialApp"
Posted by maxpoon on June 27, 2007 at 09:12 AM | Permalink
| Comments (0)
Background
Apart from showing quite an
example of easy enhancement of JSF-based web application as discussed
earlier in "Extending
the NetBeans Tutorial JSF-JPA-Hibernate Application, Part 1 -
Co-ordinating Query Views Based on Parameter Passing from JSF View to
Managed Bean", the NetBeans tutorial JSF-JPA-Hibernate application
created ('SimpleJpaHibernateApp') can also be easily extended to
demonstrate JMX
monitoring on Hibernate v3 and
the latest Ehcache 1.3.0
-
the respective very common open
source Java object/relational persistence and caching implementations,
which have
also included support for JMX
to enable monitoring on their
operational states and statistics, including the overall (e.g. query
and 2nd level cache) cache hit/miss
statistics, time of the slowest query (from Hibernate
v3), and
individual cache hit/miss statistics (from Ehcache 1.3.0).
These
monitoring capabilities give
very helpful information for application developers and administrators
to understand actual behaviour of their applications deployed, for
resource usage optimisation and performance tuning.
The following shows the configurations
to use Ehcache 1.3.0, followed by configurations of JMX monitoring on
Hibernate v3 and Ehcache 1.3.0, for both :
- Hibernate Core v3 applications
- JPA-with-Hibernate applications
Since JMX monitoring configuration :
- on Ehcache requires the latest Ehcache 1.3.0
- on
JPA-with-Hibernate application is also based on the configuration for
Hibernate Core
v3 application
we shall proceed in the following
sequence :
- Configuring
HibernateTutorialApp/HibernateTravelPOJO to use Ehcache 1.3.0
- Configuring
HibernateTutorialApp/HibernateTravelPOJO to enable JMX monitoring on
Hibernate and Ehcache
- Configuring
SimpleJpaHibernateApp to use Ehcache 1.3.0
- Configuring
SimpleJpaHibernateApp to enable JMX monitoring on
Hibernate and Ehcache
and (3) and (4) above will be discussed in next article "Extending the
NetBeans Tutorial JSF-JPA-Hibernate Application, Part 3 - Enabling JMX
Monitoring on Hibernate v3 and Ehcache 1.3, on SimpleJpaHibernateApp".
Software Requirements
(1) Configuring
HibernateTutorialApp/HibernateTravelPOJO to use Ehcache 1.3.0
As HibernateTutorialApp actually uses another application
'HibernateTravelPOJO'
supplied (in zip archive HibernateTravelPOJO.zip)
in the tutorial for its persistence POJOs, configuration to use Ehcache
1.3.0 (instead of any earlier Ehcache version bundled with Hibernate)
should be done in HibernateTravelPOJO.
| Figure
1.0 - Contents of the HibernateTravelPOJO
Project |

|
There are 2 cases for the configuration of HibernateTravelPOJO to use
Ehcache 1.3.0 :
Case 1 : If you have already set up HibernateTravelPOJO and
HibernateTutorialApp according to the NetBeans
tutorial "Using
Hibernate With the NetBeans Visual Web Pack", you may just need to
replace any previous version of the ehcache-*.jar file used (as
specified in the Netbeans "Hibernate322" Class Library in the tutorial)
with the ehcache-1.3.0.jar
from Ehcache1.3.0 downloaded, then skip to Step 1.4 below.
Case 2 : If you are just going to set up HibernateTravelPOJO and
HibernateTutorialApp, you can start with Step 1.1 below
to
set up HibernateTravelPOJO and HibernateTutorialApp to use the current
latest Hibernate 3.2.4sp1 and Ehcache 1.3.0.
Step 1.1 -
Create Hibernate Class Library in NetBeans IDE
First, follow the original NetBeans
tutorial "Using
Hibernate With the NetBeans Visual Web Pack" section "Create a
Hibernate Class Library" to create Class Library for Hibernate in
NetBeans IDE. Since the latest Hibernate 3.2.4.sp1 is
available (as at time of writing this article), it can be used in place
of Hibernate 3.2.2 suggested in the tutorial, also referring to Figure 1.1 below for
the list of jar files to be included for the NetBeans Class
Library "Hibernate3.2.4sp1".
Figure 1.1 - Create
HibernateCore3.2.4sp1
Class Library in NetBeans IDE
|

Step 1.2 - Create "Ehcache-1.3.0" Class Library in NetBeans
IDE
Download the latest Ehcache 1.3.0 (now including JMX support) from here,
unzip it, and create new NetBeans Class Library "Ehcache-1.3.0" as
shown:
Figure 1.2.1 - Create new "Ehcache-1.3.0"
Class Library for NetBeans IDE
|

Figure 1.2.2 - Add ehcache-1.3.0.jar to the
new "Ehcache-1.3.0" Class Library
|

Step 1.3 - Configure HibernateTravelPOJO to use Ehcache 1.3.0
Follow the steps of "Using
Hibernate With the NetBeans Visual Web Pack" to set it up, but with
the our new NetBeans Class Libraries "HibernateCore3.2.4sp1" and
"Ehcache-1.3.0" as follows.
Figure 1.3 - Add Library "Ehcache-1.3.0" to
HibernateTravelPOJO
|

Step 1.4 -
Configure Hibernate to use Ehcache 1.3.0
To configure Hibernate v3 to use Ehcache 1.3.0, we shall start with
modifying the Hibernate configuration file hibernate.cfg.xml as shown in Code
Listing 1.4.1 (additional settings required in bold) to
enable Hibernate 2nd-level caching using Ehcache on the following
classes and collection for HibernateTravelPOJO :
- Class hibernatetravelpojo.Person with
read-write mode
- Class hibernatetravelpojo.Trip
with
read-write mode
- Collection hibernatetravelpojo.Person.trips with
read-write mode
Meanwhile, we also need to modify the Hibernate mapping files
- hibernatetravelpojo/Person.hbm.xml
- hibernatetravelpojo/Trip.hbm.xml
as shown in Code Listing
1.4.2 and Code Listing
1.4.3 (again, additional settings
required in bold).
Code
Listing 1.4.1 - Modified hibernate.cfg.xml for HibernateTravelPOJO
|
<?xml version='1.0'
encoding='utf-8'?>
<!DOCTYPE
hibernate-configuration PUBLIC
"-//Hibernate/Hibernate
Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Data Source Name -->
<property name="hibernate.connection.driver_class">
org.apache.derby.jdbc.ClientDriver</property>
<property name="hibernate.connection.url">
jdbc:derby://localhost:1527/travel</property>
<property
name="hibernate.connection.username">travel</property>
<property
name="hibernate.connection.password">travel</property>
<!-- SQL dialect -->
<property
name="hibernate.dialect">
org.hibernate.dialect.DerbyDialect</property>
<!--
Debug logging of SQL statements -->
<property
name="hibernate.show_sql">true</property>
<!-- Enable Hibernate's automatic session context
management -->
<property
name="hibernate.current_session_context_class">thread</property>
<!-- Enable Hibernate statistics generation -->
<property
name="hibernate.generate_statistics">true</property>
<!--
Cache Configurations -->
<!--
Using net.sf.ehcache.hibernate.SingletonEhCacheProvider instead of
net.sf.ehcache.hibernate.EhCacheProvider ensures the same instance
of
CacheManager is referred to by both Hibernate and our JMX Agent
simpleJpaHibernateApp.agents.jmxAgent. (Thanks to Greg Luck!)
-->
<property name="hibernate.cache.provider_class">
net.sf.ehcache.hibernate.SingletonEhCacheProvider</property>
<property
name="hibernate.cache.provider_configuration">
/ehcache.cfg.xml</property>
<property
name="hibernate.cache.use_minimal_puts">false</property>
<property
name="hibernate.cache.use_query_cache">true</property>
<property
name="hibernate.cache.use_second_level_cache">true</property>
<property
name="hibernate.cache.use_structured_entries">true</property>
<!-- Mapping Files -->
<mapping resource="hibernatetravelpojo/Person.hbm.xml"/>
<mapping resource="hibernatetravelpojo/Trip.hbm.xml"/>
</session-factory>
</hibernate-configuration>
|
Coding
Listing 1.4.2 - Modified
Person.hbm.xml
|
<?xml version="1.0"
encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="hibernatetravelpojo.Person" table="PERSON">
<!-- Class Cache -->
<cache usage="read-write"/>
<!-- Primary Key -->
<id name="personId" column="PERSONID">
<generator class="increment"/>
</id>
<!--
Direct Data Properties -->
<property
name="name"
column="NAME"/>
<property name="jobTitle"
column="JOBTITLE"/>
<property name="frequentFlyer"
column="FREQUENTFLYER"/>
<!-- Relationship References -->
<set name="trips" table="TRIP" lazy="true" inverse="true"
cascade="all-delete-orphan">
<!-- Collection Cache -->
<cache usage="read-write"/>
<key column="PERSONID"/>
<one-to-many class="hibernatetravelpojo.Trip"/>
</set>
</class>
</hibernate-mapping>
|
Code
Listing 1.4.3 - Modified Trip.hbm.xml
|
<?xml version="1.0"
encoding="UTF-8"?>
<!DOCTYPE
hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class
name="hibernatetravelpojo.Trip" table="TRIP">
<!--
Class Cache -->
<cache usage="read-write"/>
<!--
Primary Key -->
<id
name="tripId" column="TRIPID">
<generator class="increment"/>
</id>
<!--
Direct Data Properties -->
<property name="personId"
column="PERSONID"/>
<property name="depDate"
column="DEPDATE"
type="date"/>
<property name="depCity"
column="DEPCITY"/>
<property name="destCity"
column="DESTCITY"/>
<property name="tripTypeId"
column="TRIPTYPEID"/>
</class>
</hibernate-mapping>
|
Also, the following Ehcache configuration file ehcache.cfg.xml
is required in the root of Java source directory together with hibernate.cfg.xml.
Code
Listing 1.4.4 - ehcache.cfg.xml for HibernateTravelPOJO
|
<?xml version="1.0"
encoding="UTF-8"?>
<ehcache
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd">
<diskStore
path="java.io.tmpdir"/>
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
diskPersistent="true"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"
/>
<cache
name="hibernatetravelpojo.Person"
maxElementsInMemory="300"
eternal="true"
overflowToDisk="false"
/>
<cache
name="hibernatetravelpojo.Trip"
maxElementsInMemory="300"
eternal="true"
overflowToDisk="false"
/>
<cache
name="hibernatetravelpojo.Person.trips"
maxElementsInMemory="300"
eternal="true"
overflowToDisk="false"
/>
</ehcache>
|
With the above configuration, compile the project HibernateTutorialApp
and run in NetBeans IDE, right-click on HibernateTutorialApp project
and select
[Clean and Build], then [Deploy Project], followed by [Run Project],
giving the following
Figure
1.4 - HibernateTutorialApp with inital Trip query for Person "Able,
Tony"
|

(2) Configure JMX
Monitoring
for HibernateTutorialApp/HibernateTravelPOJO
Enabling JMX monitoring for an application typically involves the
creation of following :
- JMX MBean - which can represent a device, an application,
or any resource that needs to be managed.
- JMX Agent - which is an
application that registers MBean(s) with a MBeanServer,
e.g. the platform MBeanServer.
In case of Hibernate, the MBean is provided via :
followed by MBean registration via :
where objectName is your assigned registration ObjectName for statMBean
on the instance of MBeanServer.
In case of Ehcache, four types of 'pre-fabricated' MBeans have already
been provided, including :
- CacheManager MBean
- Cache MBean
- CacheConfiguration MBeans
- CacheStatistics MBeans
together with net.sf.ehcache.management.ManagementService
which provides convenient registration (instead of individual handling)
of all these four MBeans for the instance of CacheManager
being used :
where registerCacheManger, registerCache, registerCacheConfiguration,
registerCacheStatistics are the boolean flags to indicate whether the
respective MBeans are to be registered, under the ObjectName domain net.sf.ehcache.
Hence, to enable JMX monitoring on Hibernate and Ehcache, we simply
need to create a JMX Agent that registers the appropriate Hibernate and
Ehcache MBeans with our MBeanServer.
Step 2.1 -
Create JMX Agent with Hibernate and Ehcache MBeans
Registration Codes
First, open the HibernateTravelPOJO project in NetBeans IDE, and create
our
new JMX Agent (as shown in Figure
2.1.1), specifying it as "JmxAgent"
inside the package "hibernatetravelpojo.agents" (as shown in Figure
2.1.2), followed by Adding JMX registration code (as shown in
Figure 2.1.3).
Figure
2.1.1 - Creating file with type "JMX
Agent" under "Management" Category
|

Figure
2.1.2 - Specifying the new
'JmxAgent' in package 'hibernatetravelpojo'
|

Figure 2.1.3 -
Adding MBeans registration
codes for Hibernate and Ehcache in JmxAgent
|

The additional MBean registration codes are highlighted in bold in the
following code listing.
Also, we need to modify the getDefault
method (also as highlighted in bold)
to take the SessionFactory
as parameter from the calling context instead of getting it again.
Code Listing 2.1 - JmxAgent.java
(Hibernate and Ehcache MBeans registration codes in bold)
|
/*
* JmxAgent.java
*
*/
package hibernatetravelpojo;
import java.lang.management.ManagementFactory;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.management.ManagementService;
import org.hibernate.SessionFactory;
import org.hibernate.jmx.StatisticsService;
/**
* JMX agent (singleton) for monitoring Hibernate and Ehcache in the
* 'extended' HibernateTravelPOJO example application from NetBeans
* tutorial "Using Hibernate With the NetBeans Visual Web Pack"
* at http://www.netbeans.org/kb/55/vwp-hibernate.html, which uses:
* <ul>
* <li>JavaServer Faces (JSF) web-tier</li>
* <li>Hibernate Core (3.2.4.sp1)</li>
* <li>Ehcache 1.3.0</li>
* </ul>
*
* @author Max Poon (maxpoon@dev.java.net)
*/
public class JmxAgent {
/**
* Register MBeans, enable Hibernate & Ehcache JMX Statistics
* @param sf org.hibernate.SessionFactory to be passed in from
* the invoking context (instead of creating it again
* here which is expensive operation)
*/
public void init(SessionFactory sf) throws Exception {
// Define ObjectName of the MBean
ObjectName on = new ObjectName
("Hibernate:type=statistics,application=HibernateTravelPOJO");
// Enable Hibernate JMX Statistics
StatisticsService statsMBean = new StatisticsService();
statsMBean.setSessionFactory(sf);
statsMBean.setStatisticsEnabled(true);
mbs.registerMBean(statsMBean, on);
/**
* Enable Ehcache JMX Statistics
* Use CacheManager.getInstance() instead of new CacheManager()
* as net.sf.ehcache.hibernate.SingletonEhCacheProvider is used
* to ensure reference to the same CacheManager instance as used
* by Hibernate
*/
CacheManager cacheMgr = CacheManager.getInstance();
ManagementService.registerMBeans
(cacheMgr, mbs, true, true, true, true);
}
/**
* Returns an agent singleton.
*/
public synchronized static JmxAgent
getDefault(SessionFactory sf)
throws Exception {
if(singleton == null) {
singleton = new JmxAgent();
singleton.init(sf);
}
return singleton;
}
public MBeanServer getMBeanServer() {
return mbs;
}
// Platform MBeanServer used to register your MBeans
private final MBeanServer mbs =
ManagementFactory.getPlatformMBeanServer();
// Singleton instance
private static JmxAgent singleton;
}
|
Step 2.2 -
Modify HibernateUtil.java to initiate JMX Agent
We need to instantiate the JMX Agent
somewhere, in case applications such as HibernateTravelPOJO which uses hibernatetravelpojo.HibernateUtil
to get the Hibernate SessionFactory,
HibernateUtil is a good place to do it.
Code Listing 2.2 - hibernatetravelpojo.HibernateUtil.java with modifications needed
in bold
|
package hibernatetravelpojo;
import org.hibernate.*;
import org.hibernate.cfg.*;
/**
* HibernateUtil.java of HibernateTravelPOJO example application from
* NetBeans tutorial "Using Hibernate With the NetBeans Visual Web Pack"
* at http://www.netbeans.org/kb/55/vwp-hibernate.html
*
* @author Max Poon (maxpoon@dev.java.net)
*/
public class HibernateUtil {
private static final SessionFactory sf;
static {
try {
//
Create the SessionFactory
sf =
new Configuration().configure().buildSessionFactory();
//
Initiate JMX Agent
JmxAgent.getDefault(sf);
} catch (Throwable ex) {
// Ensure you log the exception somehow, as it might be swallowed
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sf;
}
}
|
Now, HibernateTutorialApp can be recompiled by right-clicking on
[HibernateTutorialApp] project in NetBeans IDE and selecting [Clean and
Build Project] (which automatically
recompiles HibernateTravelPOJO), and tested by :
- requesting http://localhost:port/HibernateTutorialApp in
browser, or
- right-click on the [HibernateTutorialApp] project in NetBeans IDE
and select [Run Project]
to observe that shown in Figure 1.4 again,
and to
try querying the Trip's for
the
other Person's.
The application should now be executing successfully so it is ready for
observation of JMX metrics in the following Step 2.3.
In case of problems, the application server server log can be checked.
Step 2.3 - Use
JConsole to Observe JMX Statistics
Start JConsole
and connect to the JVM running GlassFish (indicated by
"com.sun.enterprise.server.PELaunch" in JConsole) via JMX Dynamic
Attach :
Figure 2.3.0 - JConsole attaching to JVM
running GlassFish (com.sun.enterprise.server.PELaunch) via JMX Dynamic
Attach
|

|
Go to JConsole [MBeans] and expand on
[Hibernate>statistics>HibernateTravelPOJO>Attributes] to view
Hibernate Statistics (as shown in Figure 2.3.1) which
include :
- Collection Statistics
- Role Names, Fetch Count, Load Count, Recreate Count, Remove
Count, Update Count
- Entity Statistics
- Entity Names, Delete Count, Fetch Count, Insert Count, Load
Count, Update Count
- Query Statistics
- Queries, Hit Count, Miss Count, Cache Put Count,
Execution Count, Execution Max Time, Execution Max Time Query String
- Second Level Cache Statistics
- Cache Region Names, Cache Hit Count, Cache Miss Count, Cache
Put Count
- Session and Transaction Counts
- SessionFactory JNDI Names, Session Open Count, Session Close
Count, Transaction Count
Figure
2.3.1 - JConsole showing Hibernate
Statistics for HibernateTravelPOJO
|

Note that the statistics as shown in the Figure 2.3.1 agrees with the
HibernateTutorialApp's invocation of initial query page which retrieves
5 Trip
instances for the
"Able, Tony" Person
instance of as shown in Figure
1.4, :
* EntityLoadCount = 11
=> HibernateTutorialApp's Page1#prerender()
(as shown in Code Listing 2.3.1)
invoking :
- SessionBean1.getPersonOptions()
to load all 6 available
instances of Person
available.
- SessionBean1.getTripDataProvider().refreshTripsList(
new
Integer((String)firstPerson.getValue()) )
to load all 5 available
instances of Trip
available for the "Able, Tony" Person
instance
* CollectionLoadCount = 1
=> HibernateTutorialApps's Page1#prerender()
(as shown in Code
Listing 2.3.1) invoking :
- SessionBean1.getTripDataProvider().refreshTripsList(
new
Integer((String)firstPerson.getValue()) )
to load 1 collection
of instances
of Trip
available for the "Able, Tony" Person
instance
* SecondLevelCachePutCount =
EntityLoadCount + CollectionLoadCount = 12
- as the loaded entities and collection are put into the respective
caches
Code
Listing 2.3.1 - Page1#prerender()
method
|
...
public void prerender() {
try {
if
(dropDown1.getSelected() == null ) {
SessionBean1 sb1 = getSessionBean1();
if (sb1 == null) {
log("Null \"SessionBean1\" from Page1#prerender()");
} else {
Option[] personOptions = sb1.getPersonOptions();
if (personOptions == null) {
log("Null \"PersonOptions\" from Page1#prerender()");
} else {
Option firstPerson = personOptions[0];
sb1.getTripDataProvider().refreshTripsList(
new Integer((String)firstPerson.getValue()));
}
}
}
} catch
(Exception ex) {
log("Error Description", ex);
error(ex.getMessage());
}
}
...
|
The cache configurations for each of the Entity Cache are available via
the Ehcache CacheConfiguration MBeans, e.g. as shown for Person in
Figure 2.3.2.
Figure 2.3.2 - JConsole showing Ehcache
CacheConfiguration for hibernatetravelpojo.Person
|

While, individual cache statistics (e.g. for entity, collection, query,
and 2nd level cache) should be available programmatically from
Hibernate JMX
statistics, e.g.
various cache statistics are available directly from Ehcache as MBean
attributes for display by JConsole without need for further
programmatic retrieval, as shown in
- Figure 2.3.3
for
class cache for Person
- Figure 2.3.4
for class cache for Trip
- Figure 2.3.5 for
collection cache for PersonTrip
- Figure 2.3.6
for StandardQueryCache (showing it not being used)
- Figure 2.3.7
for Ehcache
Cache and CacheManager Operations
- per Cache operations : flush(),
removeAll()
- CacheManager operations : clearAll(),
getCache(), shutdown()
Continue Reading...
"Introduction to the Spring Framework in NetBeans IDE" Tutorial by Troy Giunipero and Craig MacKay
Posted by maxpoon on June 15, 2007 at 11:32 PM | Permalink
| Comments (0)
If you are a Spring Framework
developer, you will find the Spring Framework Module
for NetBeans useful as it provides :
- Framework Support (enables the Spring Framework as an option when
creating a new web application)
- Spring XML Catalog (provides Spring related XSD and DTD's to
enable XML code completion)
- Integrated Library Management (installs libraries required for
the Spring Framework, as well as additional required libraries)
This Spring
Framework Module for NetBeans was also used in my JavaOne
2007 Hands-On Lab 1420 "Non-intrusive Java Application Monitoring and
Troubleshooting using JMX, JConsole and AOP". And Craig MacKay, author of this
Spring Framework Module for NetBeans, and Troy
Giunipero have written a very good tutorial article on the
module. Refer to this "Introduction
to the Spring Framework in NetBeans IDE" tutorial for more details.
Extending the NetBeans Tutorial JSF-JPA-Hibernate Application, Part 1 - Co-ordinating Query Views Based on Parameter Passing from JSF View to Managed Bean
Posted by maxpoon on June 13, 2007 at 12:47 PM | Permalink
| Comments (0)
Background
The NetBeans tutorial "Using
Hibernate With the Java Persistence API" nicely demonstrates, by
using the
NetBeans IDE, easy construction of :
- Java Persistence API (JPA) entity classes from given database
schema (using NetBeans IDE bundled 'sample' database)
- JavaServer Faces (JSF) CRUD application (on the 'sample'
database) using
JPA and entity classes generated above
The follow-up tutorial "NetBeans
Wiki - UsingHibernateWithJPA" further shows usage of JPA as well as
Hibernate-specific facilities, including :
While the above-mentioned two tutorials demonstrate ease of
JSF-JPA-Hibernate application construction with usage of JPA and
Hibernate facilities in the persistence-tier, it is interesting to
explore also on the flexibility and power of JSF in the web-tier.
As the resulting created application provides individual
CRUD functions to the actually mutually-associated entity classes, it
makes sense to see how, using JSF,
we can, easily in the two steps described, extend the application to
add new web query views from the CRUD view of one entity class to list
the links to CRUD views of its associated entity classes with re-use of
existing individual CRUD views as much as possible. This is an
example of co-ordinating query views based on parameter passing from
JSF View to Managed Bean. Adding a
'new view' to list all Products associated with a selected ProductCode
via the ProductCode-Product one-to-many association is used here.
Extending The Sample Application
Based on the "Using
Hibernate With the Java Persistence API" tutorial (but choosing the
sample database tables
ProductCode, Product, and Manufacturer instead of Customer and DiscountCode), our JSF-JPA-Hibernate
sample application (let's call it 'SimpleJpaHibernateApp')
can be created. (Please refer to the original tutorial for other
details of software needed and environment set-up).
Figure 1 - 'Sample' Database Tables to be
used by SimpleJpaHibernateApp
|
|
At this time, our SimpleJpaHibernateApp created provides individual
CRUD functions to the three actually associated entity classes (e.g.
both ProductCode-Product and Manufacturer-Product having
one-to-many associations).
Here, we shall pick the ProductCode->Product
navigation (i.e. enquiring on all Products
for CRUD, given a selected ProductCode)
since there are 6 ProductCodes
and 30 Products (so it's in
average 1:5 ratio) from the out-of-the-box NetBeans 'sample' database.
In this case, our application (and the targeted new query function)
should be as follows, starting with its home page with the HTML links
to :
- "List of ProductCode" -
listing all the ProductCodes
records (in the 'sample' database)
- "List of Product" -
listing all the Products
records
- "List of Manufacturer" -
listing all the Manufacturer
records
Figure 2 - SimpleJpaHibernateApp Home Page
|
Let's start the query navigation with ProductCode
by clicking on the "List of ProductCode"
link to lists all the ProductCodes
:
Figure 3 - "Listing ProductCodes" Page
|
Then, click on one of the ProductCodes,
e.g. "SW" in ProdCode column, the " |