Saturday, February 21, 2009

Struts 2 Ajax with JSON plugin

Heurekaaa!

I've managed to get the Struts 2 JSON plugin working. Surprisingly the thing works out of the box. Just initialize all of the stuff that you have there in the howto and you have Ajax with JSON data-transport. I even managed to integrate the example right into my application.

Maybe I'll be more verbose on the subject next post but i'ts 2 AM and I've earned my sleep for today.


PS: While researching the subject I also found this very recent presentation about JSON/Bayeoux/Comet generally and the Weblogic "Comet" API.

Thursday, February 12, 2009

Copying Hibernate objects

Today I had to copy my data in a MySQL database. My application uses Spring/Hibernate. Basically I had some rows in a database in multiple tables with relations and needed to make a copy of those with some of the data modified in the process.

Well I am an "ex" PHP guy, so ofcourse the most straightforward way should be the correct way - shouldn't it! Lets see. Our application uses Hibernate with POJO-s and manages all the data on object level. And I don't want to designate all the fields of a row (=properties of the object) one by one when copying. So I should just:
1. query the object form DB
2. give the object a new identity (reset the ID-s of that object with new ones and/or clone the object ) .
3. modify the new object according to our requirements (assign new relations, set some relations null, ...)
4. insert the object back to DB
Should be easy ... well not quite.

Hibernate keeps track of my POJO-s in a draconian CIA way, not a straightforward PHP way :). When I nullify the ID-s Hibernate just changes the existing object and since it is the same object the DB will be UPDATE when executing em.merge() or em.persist() . So I relly needed to eather clone the object using the "cloneable" interface or detach the object and modify the detached object. I could detach the object by serializing it or closing the EntityManager session but both methods are a bit too cumbersome to me for this simple task. I just need a simple way to copy database rows, something like this:

Object new_obj=copy(old_obj); em.persist(new_obj); .

So here comes the Hibernate3BeanReplicator .It does all the dirty work and still leaves me in control of the copying process. Like this:


Hibernate3BeanReplicator r = new Hibernate3BeanReplicator(null, null, null);
Object o_obj_new = r.copy(o_obj);
o_obj_new.setSomeRelation(null);
o_obj_new.setSomeIntField(0);
o_obj_new.setID(null); // we need to nullify the ID so that Hibernate will treat the result as a new object not a detached instance of an existin object
em.persist(o_obj_new);

Thursday, January 29, 2009

Hello world!

Hello world!

This is my real first post here on blogger.com . I have been keeping my own blog in one of my servers Roller install and it's been boring - no visitors :P . So I'll be submitting all my old postings and then start posting here from now on.

All the best.

Sunday, January 25, 2009

Struts 2/dojo datepicker tag sucks with non US locale

I have been messing around with Struts 2 datepicker tag. The goal is to submit date and time for a date field.

You make a Date field in Struts 2 action object. And you put in your JSP the datepicker tag like this:

<s:datetimepicker name="date_planned_date" label="" displayformat="dd.MM.yyyy" type="date" value="%{date_planned_date}" />
Now it is important not to get the locales mixed up. So I have been forcing the locale on EVERY form like that:

<s:hidden name="request_locale" value="et_EE" />
And just in case I have my locale also specified in struts.xml:

<constant name="struts.locale" value="et_EE" />
Anyway this setup doesn't work, because datepicker is not able to parse the date in the "value" param. So we omit the value param and things start working. But in our case we NEEDED the value param, because we also wanted to submit time but we didn't want to use the built-in TIME picker, but instead a text-field.

So the solution for us was to make two separate String fields in our Struts 2 application to wich we submited the date and time part of the datetime. And upon saving to DB we constructed the date out of those string fields.

With s:datepicker any "out of the box" setup for i18n does not work and as always with Struts customizations need a lot of extra coding. The datepicker tag should just work with ANY date it is given with the "value" param. Currently it does not - Java's hard work and no fun!

Wednesday, January 21, 2009

Hibernate query logging with binded parameters

I've been struggling with Hibernate queries before. Now I took the time to research this and ended up with another fucked up situation in Java world. There really is no "best practice" AND easy way of capturing queries (HQL/SQL) that are executed on DB in Hibernate.

Basically there is these alternatives:

1. Hibernate built in options ( a good description here )
2. Use Jamon, P3Spy or another similar tool
3. Custom query translator for Hibernate ( see here )
4. SQL database general query log (if applicabel to your database)

Among these only P3Spy, Custom translator, and query log have the ability to display binded query parameters within the query. So that you can copy/paste the query to your SQL tool/terminal. P3Spy project is on ice and custom query translators don't really sound like "best practice". General query log depends on DB. And should you really be spending your time programming custom translators?

Not least but last: the methods above display ALL the queries executed! When using Hibernate built-in options the data flow is way too moch for a web page that has maybe 20 queries on page load.

So there is NO NICE way of debugging that one runaway query in Hibernate/JPA. This is just NOT ACCEPTABLE. We need to be able to turn debugging on/off in Java code when making queries. Heck, my custom built data layer in PHP has the ability!

Tuesday, January 20, 2009

Struts 2 JSP select tag woes

Today I have been sucking around with a Struts 2 tag that is really selfish. I need a multiple select that has preselected values.

Now since I don't want to spend much time for this implementation I am saving these values in a text field in database. And please don't tell me that there is another "correct" way of doing it (maybe saving the values as a realations in a table). Now the items in dropdown come from DB table with primary key ID-s as dropdown values.

And now we get to the fun part - Struts2 "s:select" tag is type safe! Since my list values come from DB primary keys they are integers. Since I want to store the selected values in a text field, they are strings. If I do string.split(), I still get strings. Struts 2 does'nt have a simple solution to this. I just have to save the same type of values in DB or convert the type of the values someplace. So there is no one-line approach to make preselected values in this setup.

---rant on---
Message to Struts/JSP developers. In the view level there has to be simple solutions to these kind of problems or Struts just will be tossed aside. So please, make a simple parameter to s:select that forces comparing strings whatever the source types are. Ups Struts is open source so I might just as well blame myself :p .
---rant off---

Friday, August 1, 2008

Struts 2 and Hibernate gotcha

This post will be a short one, since struts2/hibernate has taken already too much of my time lately :( .

We have a web application set up like this example here . For some time now I have been wrestling with a problem that right after insert joined data for my Entity bean does not appear in my JSP. The same problem is documented in this thread here.

I've been actively searching for a solution to this problem for a few days now. As it turns out the culprit is Hibernate caching. You can find a small overview of Hibernate caching here . For us the simple solution was to turn off hibernate second level cache altogether. And now our applicationContext.xml has this in it:


<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource">
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="MYSQL">
<property name="showSql" value="true">
</property>
</property>
<property name="jpaPropertyMap">
<map>
<entry key="hibernate.cache.use_second_level_cache" value="false">
<entry key="hibernate.cache.use_query_cache" value="true">
<entry key="hibernate.cache.provider_class" value="net.sf.ehcache.hibernate.SingletonEhCacheProvider">
<entry key="hibernate.show_sql" value="true">
<entry key="hibernate.use_sql_comments" value="false">
<entry key="hibernate.format_sql" value="false">
</entry></entry></entry></entry></entry></entry></map>
</property>
</bean></property></property></bean>

Now that was productive for a few days work - wasn't it? Extremely user friendly indeed!!!