Accessing custom Properties from JBoss AS

Posted by Martin Cabrera on October 07, 2011

Hi everyone !

I have this issue / trouble several times. I would love share this tips with the JBoss coomunity … particularity JBoss Application Server (AS) developers.

Problem:

I have a scenario to access certain key values from a config file. I need Access to this properties file from a Java application (WAR or JAR) deployed in a JBoss AS

Solutions

1- Hard Code the path (no please !!)

Hard Code the path and create a Properties instance.

InputStream inStream = new FileInputStream(PATH_CONFIG+"config.properties");
Properties instance = new Properties();
instance.load(inStream);
//access to a property
String value = instance.getProperty(key);

2- Using JBoss System Properties (almost)

Avoid to Hard Code … use a tool from JBoss. System.getProperty()

JBoss allows access to a standard set of properties. For instance: jboss home dir (“jboss.server.home.dir). Here I share some piece of code to make an instance of this properties file.

String path = System.getProperty("jboss.server.home.dir")+"/conf/config.properties";
InputStream inStream = new FileInputStream(path);
Properties instance = new Properties();
instance.load(inStream);
//access to a property
String value = instance.getProperty(key);

3- Using Resource bundle (the best !)

JBoss AS add to the classpath a lot of folders and jars. One of them is the “config” folder into the server domain. eg. “server/default/conf”

ResourceBundle objects contain an array of key-value pairs. You specify the key, which must be a String, when you want to retrieve the value from the ResourceBundle. The value is the locale-specific object.

When you create a ResourceBundle this properties file must be in the classpath.

Then we could:

ResourceBundle instance = ResourceBundle.getBundle("project.config");
//access to a property
String value = instance.getString(key);

In this example the file “config.properties” must be inside a “project” folder declared in the classpath, for instance: “config”

That’s all folk !

Auditing, History of database modifications with Hibernate – Envers Solution !

Posted by Martin Cabrera on October 27, 2010

hibernate-logo

Envers is one of the Hibernate’s project sponsored by Redhat. Works with Hibernate and Hibernate Entity Manager.

Aims to enable easy auditing of persistent classes. For each audited entity you must annotate your persistent clases with @Audited, a table will be created, which will hold the history of changes made to the entity.

The idea is very similar to CVS or Subersion. Each transaction with updates, deletes or inserts made in the database with hibernate generate a new revision number. One transaction is one revision.

Envers provide a simple way to retrive your data of a revision using: revision number, date, queries with min and max function between others.

You can use Envers wherever Hibernate works: standalone, inside JBoss AS, with JBoss Seam or Spring.

It’s very easy …

@Entity
@Audited
public class Usuario {
public enum Rol{
EMPRESA, ADMINISTRADOR,MESA_ENTRADA;
}
private Long id;
private String usuario;
private String contrasenia;
private Rol rol;
@Id
@GeneratedValue
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Entity @Audited
public class User {
	private Long id;

        @Id @GeneratedValue
        public Long getId() { return id; }
        public void setId(Long id) { this.id = id; }

        // other fields and methods
        ...
}

Envers configuration

When configuring your Hibernate (persistence.xml if you are using JPA, hibernate.cfg.xml or other if you are using Hibernate directly), add the following event listeners:

<persistence-unit ...>
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>...</class>
<properties>
   <property name="hibernate.dialect" ... />
   <!-- other hibernate properties -->

   <property name="hibernate.ejb.event.post-insert"
             value="org.hibernate.ejb.event.EJB3PostInsertEventListener,org.hibernate.envers.event.AuditEventListener" />
   <property name="hibernate.ejb.event.post-update"
             value="org.hibernate.ejb.event.EJB3PostUpdateEventListener,org.hibernate.envers.event.AuditEventListener" />
   <property name="hibernate.ejb.event.post-delete"
             value="org.hibernate.ejb.event.EJB3PostDeleteEventListener,org.hibernate.envers.event.AuditEventListener" />
   <property name="hibernate.ejb.event.pre-collection-update"
             value="org.hibernate.envers.event.AuditEventListener" />
   <property name="hibernate.ejb.event.pre-collection-remove"
             value="org.hibernate.envers.event.AuditEventListener" />
   <property name="hibernate.ejb.event.post-collection-recreate"
             value="org.hibernate.envers.event.AuditEventListener" />
</properties>
</persistence-unit>

Then, annotate your persistent class with @Audited (like the User example)

And that’s it!

Queries

Find audited data

You can access the audit (history) of an entity using the AuditReader interface, which you can obtain when having an open EntityManager.

AuditReader reader = AuditReaderFactory.get(entityManager); 
User oldUser = reader.find(User.class, userId, revision)

Search a revision number

the whole documentation is in the Web site:  http://docs.jboss.org/envers/docs/index.html#queries

To ilustrate one example I show the way to search the max number revision of one Entity audited.

Number revision = (Number) reader.createQuery().forRevisionsOfEntity(User.class, false, true)
.addProjection(AuditEntity.revisionNumber().max())
.add(AuditEntity.id().eq(userId))
.getSingleResult();

We use Envers in a few projects. Works fine and very quickly, we recomended … no dubt ! Envers

Web site: www.jboss.org/envers

Envers documentation: http://docs.jboss.org/envers/docs/index.html

JPA @OneToMany – I want a foreign key. I don’t want a Join table

Posted by Ariel Ludueña on October 18, 2010

Suppose you have this two entities: PhoneList and Phone.

PhoneList have a @OneToMany to Phone. (I need only a unidirectional relationship)

Something like:

@OneToMany(cascade=CascadeType.ALmappedBy=”phoneList”)
public List<Phone> getPhones() {
return phones;
@OneToMany(cascade=CascadeType.ALL)
public List<Phone> getPhones() {
   return phones;
}

The phone entity doesn’t have nothing special.

If you deploy those entities your JPA provider will create 3 tables. One table for each entity and also a “JoinTable”. But, why? This kind of relationship can be done by 2 tables only and I don’t want a third table. I want a PHONE table with an FK column to PHONELIST table.

How can I do that?

Two options:

  1. Make your relationship bidirectional
  2. Add an @JoinColumn in the @OneToMany attribute

Option number 1 – Make your relationship bidirectional

The problem is that “I don’t need a bidirectional relationship”! … Ok, but, suppose that you are more interested in solve this and move forward to a “real issue”.

To make this relationship bidirectional, you must add in the Phone entity the reference to the PhoneList entity with the @ManyToOne annotation. Something like:

@Entity
public class Phone {

private Long id;
private String phoneNumber;
private PhoneList phoneList;

@ManyToOne
public PhoneList getPhoneList() {
   return phoneList;
}
...

Also you have to add to the relationship @OneToMany in the PhoneList entity the mapped by attribute. Something like this:

@Entity
public class PhoneList {

	private Long id;
	private String name;
	private String description;
	private List<Phone> phones;

	@Id @GeneratedValue
	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	@OneToMany(cascade=CascadeType.ALL, mappedBy="phoneList")
	public List<Phone> getPhones() {
		return phones;
	}

Option number 2 – Add @JoinColumn in the @OneToMany attribute

If you don’t want to have a bidirectional relationship, you have to use @JoinColumn like this:

@Entity
public class PhoneList {

	private Long id;
	private String name;
	private String description;
	private List phones;

	@Id @GeneratedValue
	public Long getId() {
	  return id;
	}

	public void setId(Long id) {
          this.id = id;
	}

	@OneToMany(cascade=CascadeType.ALL)
	@JoinColumn(name="phone_list_id", referencedColumnName="id")
        public List getPhones() {
	  return phones;
	}

and the Phone entity remain without references

@Entity
public class Phone {

private Long id;
private String phoneNumber;

...

Steps to include lightweight cache in java applications – WhirlyCache 3

Posted by Martin Cabrera on May 28, 2009

Data caching is a very important consideration for JEE applications.

A classic problem for any application is to detect and solve the recurrent calls for optimizing the applications. Some cases can be:

  • database calls
  • business logic calls
  • remote method invocations

Data caching limits the number of remote invocations in distributed applications and improves performance of web applications by reducing the number of calls.

Several solutions exist to include a framework for implementing a cache.

Check out this interesting comparative table.

WhirlyCache (https://whirlycache.dev.java.net)

I use whirlycache in two projects and works really good. I recommend it to incorporate in a simple lightweight Web application
Whirlycache is a fast, configurable in-memory object cache for Java. It can be used, for example, to speed up a website or an application by caching objects that would otherwise have to be created by querying a database or by another expensive procedure. From the testing that we have done, it appears to be faster than any other Java cache that we have been able to inspect.

Steps to include WhirlyCache

(Step I) Donwload whirlycache and include it in your project -> https://whirlycache.dev.java.net/files/documents/1995/34601/whirlycache-1.0.1.zip

(Step II) Create a cache instance

CacheConfiguration cc = new CacheConfiguration();

cc.setName("KBCache");

cc.setBackend("com.whirlycott.cache.impl.ConcurrentHashMapImpl");

cc.setTunerSleepTime(60);

cc.setPolicy("com.whirlycott.cache.policy.LFUMaintenancePolicy");

cc.setMaxSize(10000);

Cache c = CacheManager.getInstance().createCache(cc);

(Step III) Use cache instance

c.store(key, object);
c.remove(key);
c.retrieve(key);

Example of java class (is a jboss seam entity class) – StockCache.java