Tuesday, May 17, 2011
Tip to Detect Connection Leaks
To detect potential connections on a Weblogic backed connection pool set the "Inactive Connection Timeout" close to zero. Setting this feature will cause the application server to forcibly close the connections which have been left inactive for the timeout period. It will print out a stack trace which will guide you where the connection is acquired and not yet released so that you could investigate.
Saturday, May 14, 2011
Paging with Hibernate
Hibernate query api has setFirstResults and setMaxResults methods that restricts the result set for ceratain amaount. Typical usage inside a generic method would be like :
public List find(String queryString, Object[] queryArgs, int first, int max) {
Query q = getEntityManager().createQuery(queryString);
if (queryArgs != null) {
setParameters(q, queryArgs);
}
q.setFirstResult(first);
q.setMaxResults(max);
return q.getResultList();
}
Here If you are using Hibernate with Oracle it will wrap the original query with a select query which will filter the result based on rowid's.
One rule of thumb while using paging is that your query shouldn't have any joins on collections. Than Hibernate will just execute the original query claiming it can't exactly determine the number of results returned. The warning "firstResult/maxResults specified with collection fetch; applying in memory!" is logged and paging only occurs on the ResultSet object.
Luckily the queries I came across mostly could be refactored so that they don't use joins on collections. Like :
EJBQuery query = new EJBQueryImpl(Foo.class, "f");
query.join(Joins.joinFetch("f.fooBooSet", "fbs"));
if(sorguKriteri.getBoo() != null){
query.addRestriction(Restrictions.addEquals("fbs.boo", sorguKriteri.getBoo()));
}
Could be rewritten as : EJBQuery query = new EJBQueryImpl(Foo.class, "f");
if (sorguKriteri.getBoo() != null) {
query.addIn("f", new EJBQueryImpl(FooBoo.class,"fb", (EJBQueryImpl) query)
.addProjections(Projections.add("fb.foo"))
.addRestriction(Restrictions.addEquals("fb.boo",sorguKriteri.getBoo())));
}
A sub select is used to filter the result instead of join.Another common pattern used with hibernate is using a lazy list which loads results, page by page basis which looks like :
public class PagingList<E> extends AbstractList<E> implements Serializable {
private Query query;
private int numOfResults = 0;
private int pageSize = 10;
private List<E> currentResults = new ArrayList<E>();
private int currentPageIndex = -1;
public E get(int index) {
int pageIndex = index / pageSize;
if (currentPageIndex != pageIndex) {
currentPageIndex = pageIndex;
currentResults = getService().find(query, currentPageIndex * pageSize, pageSize);
}
return currentResults.get(index % pageSize);
}
public int size() {
return numOfResults;
}
public PagingList(Query query, long numOfResults, int pageSize) {
this.query = query;
this.numOfResults = (int) numOfResults;
this.pageSize = pageSize;
}
public Service getService() {
return (Service) SpringUtils.getBean("service");
}
...
}
Here the query is executed when the get method is called on the list object. Down side of this approach is that query size must be determined with a separate select.
Tuesday, April 19, 2011
QMass, An API for Cluster Wide Operations
I have started a new clustering api for Java. You can access the project page at http://code.google.com/p/qmass/. Very first version is ready to be downloaded.
It's first application is an hibernate cache provider implementation. You can start using it by simply defining org.mca.qmass.cache.hibernate.provider.QMassHibernateCacheProvider as the hibernate cache provider.
By default it will try to cluster applications running on localhost in the port range 6661-6670. To configure QMass you need to set the qmass.cluster property through your persistence.xml. An example persistence.xml might look like this :
<persistence>
<persistence-unit name="app">
...
<properties>
<property name="hibernate.cache.use_second_level_cache"
value="true"/>
<property name="hibernate.cache.provider_class"
value="org.mca.qmass.cache.hibernate.provider.QMassHibernateCacheProvider"/>
<property name="qmass.cluster"
value="localhost,6661,6670/"/>
<property name="qmass.name"
value="myproject"/>
...
</properties>
</persistence-unit>
</persistence>
Cluster definition 10.10.10.112,6661,6670/10.10.10.113,6661,6670/ will define a cluster spanning two different machines with in the port range. qmass.name is the name of your cluster. By setting it you might have two or more clusters running together with out messing with each other.
Thursday, April 14, 2011
New Languages on the JVM
In case you didn't notice there is a trend for developing new languages that run on top of JVM. Jython, JRuby, Scala, Groovy, Clojure are examples. It seems latest addition will be the RedHat's Ceylon.
I have tried some of these languages. I wrote my impressions on Groovy here.
After 6 years of professional experience with Java, here is what I would do to fix it and what I wont touch.
Don't touch the packages.
Packages are convenient and simple ways to define the namespace. So I wont touch the way it is. You have to define the package keyword for every class/file and specify imports below that. I would farther force the constraint and remove the default package.
Improve the imports with alias.
Only problem I had with imports are on the rare case that, when I want to import more than one class with the same name. Alias's could be introduce to improve that. Here is how I would have used them ;
import org.apache.commons.lang.StringUtils as CommonsStringUtils;
import org.springframework.util.StringUtils as SpringStringUtils;
...
if(CommonsStringUtils.isEmpty(str)) {
...
One more rule I would have on defining an alias is that you can't define alias if there is not any naming collision. This would prevent the abuse of use.
One public class per file.This is a rule that most of the languages remove, which I object. I like it and won't touch it. With the packaging rules and this, I can find the source code of the class easily.
Access modifiers.
Remove the private keyword from language and make the default visibility private for classes and variables. If needed introduce a separate keyword for package level visibility.
No headless files.
Another common trade of the new languages are letting the users code without any class definition. Like a single lined print statement without any class definition is a valid program. I don't think enabling this freely would encourage anything more than some garbage scripts.
Improve Getters Setters, Simplify Initializing Constructors
Java Beans spec. dictates that a bean should define private fields and make these fields accessible through what we call getter/setter methods. This is widely used in today's apps. and frameworks. Hibernate and other JPA frameworks use it extensibly.
I believe getter/setter methods are mostly useless and clutters the code.
Again another source for boilerplate code is the initializers.
I think best way to solve this is by introducing new meta information.
public class City {
public get String name; // public getter no setter
public get set Integer population; // public getter - setter
public get protected set Integer foo; // public getter - protected setter
}
...
tokyo.getName(); // to use
So public or package level visibility for a field must be used with get/set keywords. Specifically defining the get/set methods will override the default methods. And at last I believe that setters should return 'this'.
For the constructors I don't have any solution that I like for now. Groovy and some others might too, have a map syntax for constructors.
No Primitives
Java has distinction between 1L and the Java Long object. They should be same. Constructors for Long object must be removed and typing 1L should create the Long object. Again method calls could be made like 1L.toString()
Null checks
Again a common source for boilerplate code. I like the Groovy solution :
if(state != null &&
state.getTransitions() != null &&
state.getTransitions().size() > 0) {
states = state.getTransitions().values();
} else {
states = new ArrayList();
}
Could be written as :
states = state?.transitions?.values() ?: new ArrayList(); ? is the null check and ?: is called the elvis operator.
Closures
Another popular construct that people try to add is the closures. Closures are simply function blocks that could be passed as parameters to methods or other functions. This is what closures look like in Java :
jdbcTemplate.doInConnection(new ConnectionClosure<Long>() {
@Override
public Long execute(Connection con) throws Exception {
ResultSet set = con.createStatement().executeQuery("select max(id) from cacheoperations");
while (set.next()) {
return new Long(set.getLong(1));
}
return new Long(0);
}
});
That is the OO way to define a closure. I am sure that on many enterprise apps. some similar code for accessing a Connection object exists. We don't want unclosed connections so we employ this pattern to be sure that connection is closed after the closure is done. While this works it's cumbersome to define. Every closure needs an interface with just one method to be defined. In this case the ConnectionClosure interface. Improved version with no interface might look like this :public class JDBCTemplate {
public Object doInConnection(Object execute(Connection con)) {
...
// use
jdbcTemplate.doInConnection(
Long execute(Connection con) throws Exception {
ResultSet set = con.createStatement().executeQuery("select max(id) from cacheoperations");
while (set.next()) {
return new Long(set.getLong(1));
}
return new Long(0);
});
To improve code use any object containing a method with the mentioned signature could be passed as argument to this function.What needs to be thought further is how this would effect the Java api design.
Biggest Don'ts
Don't change the Java's basic syntax. Don't add pascal like begin and end keywords for blocks. Curly braces are enough. Same thing for loops and if statements. I don't think there is a need for introducing a new assignment operator like :=.
Tuesday, March 29, 2011
Comparing different cache products
My app. relies heavily on cache to function. Although I use cache on the view, I use it mostly as Hibernate 2nd level cache. Here are some of the products I used and what I think about them.
Ehcache
I think this was used to be called Easy Hibernate Cache and Hibernate people promoted it's use. Now it's owned by Terracotta. I used this quite for a while, it's light, fast and mostly easy to use. However it didn't worked that good as a distributed cache environment.
It has multicast support for peer discovery which works pretty well for most of the time. Except it didn't worked on our prod environment where we have 10 nodes across the network. Some of the nodes just didn't connect to each other which is unacceptable.
It also has manual peer discovery, which needs different ehcache.xml's which would point to other nodes. I think you could tell hibernate, which xml to use at persistence.xml file.
Still I had hard time tracking which node joined to the cluster and which failed to.
Memcached
Main reason I tried memcached was, its use at facebook, wikipedia and such. Memcached is designed a bit different from the ehcache. This is written in 'C', had to be build and run as a daemon process. Cache clients can connect to it through telnet and perform. First problem I ran into was building it. Although It build easily on a Linux environment It required some editing to headers on a HP-UX in order to compile. Second and greater problem is, it doesn't have support for Hibernate. I used the library here http://code.google.com/p/hibernate-memcached/ which is not being actively developed anymore. It also has some nasty bugs...
Hazelcast
Hazelcast is what I use now. At first look it's design looks similar to ehcache but this one is made distribution in mind. It's distributed by default. I have enabled back-up reads, and near-cache settings for better performance.
It comes whit a decent monitoring app. which you can monitor your cluster and see the active nodes.
It's much easier to configure especially compared whit ehcache.
Wednesday, December 29, 2010
Hibernate Id Generation and Oracle Sequences
I thought that @SequenceGenerator allocationSize attribute defined the number to increment the sequence. The API says that anyway... If you forget the fact that, you can't increment the Oracle Sequences more or less than the number you specified while you created them, you may find your self in a trap.
By default you create your sequences with an increment of 1. This becomes a problem if your app. does bulk inserts. Every insert will need a select to the sequence to generate an id which in turn will hinder the performance of app.
One of the ways Hibernate tries to overcome this problem is using a simple strategy called HiLo. Basically Hibernate uses the allocationSize attribute as a multiplier to sequence value. If the sequence is 'x' Hibernate uses id's from '(x-1)*allocationSize' to 'x*allocationSize' to following inserts after a single select and an increment to the sequence.
While I think this is a feasible approach, down side is all the apps. using this sequence will have to use this algorithm to generate the id's, dealing with the fixed allocationSize, or the generated id's may collide with each other.
Instead of using sequences, using a table which stores id's is much better since you can define the increment size to the amount that you actually require. Using the following annotation and the optimizer, causes a simpler and similar behavior that API actually states. Here is the annotation;
1: @GeneratedValue(strategy = GenerationType.TABLE, generator = "genFooTable")
2: @GenericGenerator(name = "genFooTable",
3: strategy = "org.hibernate.id.enhanced.TableGenerator",
4: parameters = {
5: @Parameter(name = "table_name", value = "SEQUENCES"),
6: @Parameter(name = "value_column_name", value = "NEXTVALUE"),
7: @Parameter(name = "segment_column_name", value = "NAME"),
8: @Parameter(name = "segment_value", value = "genFooTable"),
9: @Parameter(name = "increment_size", value = "10"),
10: @Parameter(name = "optimizer", value = "org.mca.PooledIdOptimizer")
11: })
The optimizer :1: public class PooledIdOptimizer extends org.hibernate.id.enhanced.OptimizerFactory.OptimizerSupport {
2: private long value;
3: private long hiValue = -1;
4: public synchronized Serializable generate(AccessCallback callback) {
5: if ((hiValue < 0) || (value >= hiValue)) {
6: value = callback.getNextValue();
7: hiValue = value + incrementSize;
8: }
9: return make(value++);
10: }
I made a little editing with the Hibernate's original pooled optimizer since I didn't like the way it work.
Cheers!Monday, December 27, 2010
Java Frameworks Presentation
My little last minute in-house java frameworks presentation :
Java frameworks
View more presentations from Murat Can ALPAY.
Subscribe to:
Posts (Atom)