Friday, September 17, 2010

SVN Merge is Evil

It is really hard. I worked on a branch for a new feature maybe 2 months. The trunk is kept with some small enhancement and bug-fix. Today is the merge day. OMG, that is hard. I used the merge in Netbeans first. After 40 minutes I seem to get all the brown sign of conflicts out and committed it. Well, that is not so bad, I thought. But soon I discovered quite some new files are missing and some are not updated. Boom! I rolled things back to last reversion and recommitted. This time I tried to do it in Eclipse. Well, it seems more conflicts pop up and I guessed that Eclipse's SVN plugin was better. I was wrong after another half an hour. Still some files were showed updated but they are definitely old. What is wrong!

It turns out that neither one handles TREE-CONFLICTs well. And yes, it proliferates for my merge. And neither provides any good way to handle it. I have to done it one at a time in command line. SVN is really dumb for tree-conflict. I checked out a clean reversion again. I merged once. It stops at certain revision. I resolved conflicts (normal ones) in Eclispe. Then I tried to hand-mark those tree-conflict as resolved. And then I merged again. This time it progressed to some further revision with some new conflicts. I marked them resolved again, merged again. .... Five, six cycles later, I finally get to the HEAD. :) The stupid things about svn is that if I added one file and later removed it in the branch, merging stops at some revision with adding the file, then next time merging removes it. Odd price to pay with a revision system with historical approach.

That is really hard!

Note: A couple of days later, I found it missed a few files. OMG! (9/20)

Tuesday, August 31, 2010

Name Parameter in HQL of Hibernate

Name Parameter in HQL is nice, like the parameter statement in sql, it is more robust than build the hql in flight and for the special characters. But it is also a little picky. It took me about 30 minutes to figure out what is wrong and the correct combination.


Session session=getSession();
String hql="from Job where (ownerId=:userId) AND ((name LIKE :keyword) OR (description LIKE :keyword) "
+" OR (flow.name LIKE :keyword) OR (flow.description LIKE :keyword)"
+"OR (flow.typeName LIKE :keyword) OR (flow.keyWords LIKE :keyword))";
Query query=session.createQuery(hql);
query.setLong("userId", userId).setString("keyword", "%"+keyword+"%");


You cannot put flow.keyWords LIKE '%:keyword%' or flow.keyWords LIKE %:keyword% in the hql, it has to go in the setString().

Tuesday, August 24, 2010

Switch to Netbeans

I get fairly frustrated by Eclipse. It is nice and polished in most sense. However, a few things keep bothering me. A few essential tools in our work needs plugins. Svn and maven plugins are both problematic. Early this year, for some reason, svn plugin keeps freezing the eclipse. Maven plugin also feels somehow weird. I did not get it through until I start to use spring's Spring Tools Suite(STS), a customized eclipse from spring source. It is kind of nice with maven built-in. I still need to install svn plugin, which does not freeze anymore. But the svn commit often fails, not sure whether I should blame the plugin or the googlecode's svn repository though. But it is likely some suboptimal setting in svn plugin. However, maven plugin (M2eclipse) still runs sluggishly and occasionally it freezes STS, especially in the MacBook Pro (4G Ram, 2.4G T8300). It often takes 10 seconds or more to open a pom.xml files, even in a fairly powerful machine ( 2.4G Core Quad, 8G Ram). Our projects are reasonably complicated, dependency in the order of 100 things. It has some nice tool for maven, such as the search in dependency. But the speed is too slow. It takes even 10 seconds to switch to a window of pom.xml. Something seriously wrong with m2eclipse.

Recently Eclipse upgrade to 3.6. I tried to upgrade. But it does not work well for me. Some common shortcut key does not work such as Ctrl-Alt-C for commit.

I don't remember how it starts. I saw netbeans a few days ago. I used netbeans before eclipse. But it is a long time ago. In recent few projects, everyone else use s eclipse, so I use it as well. Well, I took a serious look at netbeans (6.9.1) this time, to my pleasure, it has maven and svn built-in. So it should be OK for my project. Our project is a multi-module maven project. I first thought the project is eclipse specified as we commit from eclipse. And I know for sure that there are some eclipse's setting in repository. I tried netbeans and it works. It actually works pretty better than I thought. It checkout the project into several projects, each module becomes a project. It actually is better, as now each project's default paths (src/test/web/res/..) are recognized automatically into the project viewer. In eclipse, it is one project and eclipse cannot recognize the default maven paths in modules. So they are all normal folders and it is quite inconvenient to look for the path I need within about 10 different folders. One plus. Well, soon I found a few other goodies. It automatically include the default ~/.m2/settings.xml into the project. This is fairly convenient because it does control quite some properties in the project and I often needs to modify it. And best of all, pom.xml opens fast. In the crude looking, it is treated as a simple xml file. And a close look shows that you can also open a dependency graph, which does take some time. But most time, I do not need to see that, I only need to work with it as simple xml.

Svn is not as powerful. It does not provide a svn repository view. However, you can checkout things and other normal tools like update, commit, merge, diff are there and that is enough for me.

And an extra plus is that it seems bundled with Spring. And I got some basic tools for spring out of box, such as bean editor...

Overall, netbeans seems to run faster. It does not looks as nice, swing is not as good as SWT. But it looks OK, and this is the secondary concerns for me. Things seems integrated more tightly in netbeans. Eclipse seems more module, everything comes in as plugin and there are lots of great plugin. But for my work, I only need those typical tools. And netbeans seems to serve me better.

I switched to netbeans and it works fine for me for a week now . We will see how it works out in more time.


Update: Dec. 16th, 2010
Two good things about Netbeans:
* It formated HTML corrected. You will definitely hate Eclipse/sprinesource when you try to auto-format html. Netbeans also take care of javascript in html <script> tag.
* Netbeans also understand javascript syntax to some degree and points out some obvious typo such as extra ";", "}", ... Javascript is nice, but hard to debug and often a small typo like that costs me half an hour as firebug/chrome developer tool does not realize it and reports some other errors and leads you everywhere but the correct place. That is a really benefit with Netbeans.

Sunday, July 18, 2010

Hibernate (2)

We use dbunit to populate the database with some data in testing phase. I tried to generate some new dbunit export with new "order" value. It always fail to load, I have to revert the data back to the time without any order data. It said it could not find the new column for "order". I finally decided to sit down and work on it. After maybe 20 minutes guessing, I figure it is probably the maven-hibernate3 plugin generated the ddl without those column. I delete this plug-in and it goes well.

I think I also found a bug in their documentation. In their example,
(3.5.1Final), the id field is declared non-nullable.

@Entity
public class Parent {
@OneToMany
@OrderColumn(name="order")
@JoinColumn(name="parent_id", nullable=false)
private List<Child> children;
...
}

@Entity
public class Child {
...
@ManyToOne
@JoinColumn(name="parent_id", insertable=false, updatable=false, nullable=false)
private Parent parent;
...
}

I have something very similar, a MirexSubmission with a list of MirexNote's. I also make the cascade from MirexSubmision.


@Entity
@Table(name="mirex_submission")
public class MirexSubmission implements Serializable {
...
@OneToMany(cascade={CascadeType.PERSIST,CascadeType.MERGE},fetch=FetchType.EAGER)
@OrderColumn(name="note_order")
@JoinColumn(name="submission_id")
public List<MirexNote> getNotes() {
return notes;
}

.....
}



@Entity
@Table(name="mirex_note")
public class MirexNote implements Serializable{
...
@ManyToOne
@JoinColumn(name="submission_id",insertable=false, updatable=false,nullable=true)
public MirexSubmission getSubmission() {
return submission;
}
...
}


However, it always give me some error when I try save (Hibernate merge()) about "no default value for "submission_id" column. It does not matter I merge the MirexNote or MirexSubmission object, in which case it cascade to MirexNote. I check the schema, "submission_id" column does not allow null value, but with out the default. And obviously, it is no wonder the insert on this table fail. Finally I change to nullable=true and things worked out.

Correction (Aug. 3rd): It seems to work fine if both ends (many-to-many, one-to-many) set nullable=false.

Friday, July 16, 2010

Hibernate

Recently I start to build an sub system for MIREX submission. It is not too complicated, it should accept submission of programs with certain metadata, such as contributors, notes, etc... And Mirex runner (NEMA system, or a human runner) should be able to change the status, leave note and inform the submitter. It is not simple when you need to consider every detail. And I have already spent about two weeks on it.

One thing I need to learn is Hibernate. We used that already in our system. But Amit and others have implemented it and provided me with a DAO object. So I have no direct interaction with it. This time, I have to write every bit from the scratch. Well, that is not totally true. I have their old code for reference. I use the annotation mapping, and spring hibernate template. I spent quite some time to read "Java Persistence with Hibernate", not the best choice. The book was written by one of the authors of Hibernate, and is very detailed and not really good for the first-timer. After couple of days, I finished about half the books and started to read the hibernate documentation from their site. It turns out much more accessible. It has some good example and explains things pretty clearly and I really like it.

Today, I realize that I need to have bi-direction many-to-one and many-to-many association with list. The order is important. I looked though the book and again, the documentation gives me an easier answer. @OrderColumn. And here comes the problem. We are using a quite mixed version of hibernate, some modules use 3.2.6, some uses 3.3.0GA and some use 3.4.0GA, with JPA 1. None of them support @OrderColum. It took me a while to figure out that this is the new annotation for JPA2. I have to upgrade hibernate in order to use this feature. Otherwise, I can use some hibernate annotation. I figured to whatever, just upgrade. So the latest 3.5.1Final we go.

The first problem I run into is that I cannot find it in the main maven repoistory. After some search, I found it is only in JBoss's repository. I need to add it into our own proxy repository server. I have to ask Amit for the username/password for it. After some talk, I found out we have already had it in the proxy list. I SHOULD HAVE tried before ask...

And soon, I found the module structure changes. Hibernate-annotation depends on hibernate-core. So I only need to include hibernate-annotation. But soon I run into the next problem, Spring cannot build the session-factory for Hibernate, it cannot find some classes about slf4j. I am confused. Hibernate already has slf4j dependence. After some 20 minutes on google, I finally figured out that Hibernate has slf4j-api. But I also need to make my code depends on slf4j12. So include it and I got new different error.

This time is ehcache. The old code has hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider. I looked at hibernate-core.jar, and sure, it dose not have such class. After a while, I realized it might not in core. I check the repository, there is one module, hibernate-ehcache. Here we go. But again, new problem pops up.

It is something about assistance. I am confused again. Hibernate does have dependency on javaassistence. A close look says that is is in test scope. Maybe that is the reason. Add the new dependency, and finally my unit tests sort of run.

My old database schema does not work with the new ordercolumn. The project has dependency on hibernate3-maven plug-in. I used to just copy their output ddl into mysql to generate the new database. But this time after I import the ddl, the test always tell me some field "note_Orders" is missing. I am really confused. I gives the @OrderColumn a new name. After run the maven test several times and I started to read the ddl more carefully and sure, the order columns are missing. WTF!!! Well, it turns out that hibernate3-maven plug-in depends on hibernate-3.4.0GA. It is probably does not understand this new annotation.

I add hibernate.hbm2ddl.auto=update into the hibernate config. And it seems to update my schema fine.

WHEW, quite some work!

Thursday, July 1, 2010

Java enum

Java 5 enum is nice, but it is not terribly well documented. The useful information is scattered around. I did a careful study maybe 2 years ago but I am a bit loss when I try to look around for its information now. So maybe it is better to document everything I need here for later reference.


A few useful links:
Type-Safe Enumerations
Using the built-in enumeration methods: values( )
Sun's Tutorial
Spring MVC form tags for enum

Monday, June 28, 2010

XStream Map<String,Ojbect> is not a good idea for Multi-Models

I guessed in an earlier post that I might be able to get multi-model work with XStream using a Map<String,Ojbect>. Well, it does not work well. The ending result is something like

{"map":
[{"entry":[
{"string":"jobs","list":[""]}, {"string":"head","org.imirsel.nema.flowservice.config.SimpleMeandreServerProxyConfig": {"host":"nema.lis.uiuc.edu","port":11714,"maxConcurrentJobs":1,"username":"admin","password":"admin"}},
{"string":"workers","map":[{"entry":"org.imirsel.nema.flowservice.config.SimpleMeandreServerProxyConfig":{"host":"nema-c-1-2","port":11714,"maxConcurrentJobs":2,"username":"admin","password":"admin"},"org.imirsel.nema.flowservice.config.MeandreServerProxyStatus":{"numRunning":0,"numAborting":0}}}]}]}]}

Not nice. It is possible in javacript, but will need quite some codes to handle. Still, I would like to stick with something required minimal massaging in javascript side. Mine current solution seems better.