Friday, December 18, 2009

Where clause in Hibernate class mapping

I have a table with a column STATUS. There are two possible values: 1 and 0. 1 means active and 0 inactive. The data with inactive status are for archives only so I'd like to filter them out in the application. Of course, I can do this in the query, criteria or filter. But I wonder if there is a way to do this in mapping, once and for all. It turns out you can. You just need to specify the "where" attribute in class mapping. For example,

<class name="my.com.Report" table="IREPORT" where="STATUS=1">



This will include the active report in query. However, as always, there is a catch. This restriction does not work by default in association. According to a reference here, if the class is on the many side of one-to-many relationship, you need to add this "where" explicitly in the one-to-many mapping. But I could not figure out how to do this yet.

Tuesday, November 3, 2009

Schema Creator for HSQLDB in Unit Testing Hibernate

I am working on an application with Spring, Hibernate and MySQL database. There are several options I can unit test Hibernate DAOs. One is to use EasyMock, but it won't really test the queries. Another one is to Spring AbstractTransactionalJUnit4SpringContextTests, connecting to a test instance of MySQL. But then the tests rely on the external resource. As an alternative, I want to use a in-memory HSQLDB during unit testing to cut the dependency. The database will be created and dropped during the tests with Hibernate property "hibernate.hbm2ddl.auto=create-drop".

Sounds great. However, here is the catch. Basically, when using in-memory HSQLDB to test Hibernate with hibernate.hbm2ddl.auto=create-drop option, Hibernate does not know to create the schema BEFORE creating tables. Thus it leads to "invalid schema name" error in unit tests.

There is an ingenious solution. It created a schema creator and define it as a "depends-on" for Hibernate session factory in Spring configuration file. It thus forces the schema creation.

public final class HSQLSchemaCreator implements InitializingBean {

/**
* schema name.
*/
private String schema;

/**
* data source.
*/
private DataSource dataSource;

// setters and getters
public String getSchema() {
return schema;
}

public void setSchema(String schema) {
this.schema = schema;
}

public DataSource getDataSource() {
return dataSource;
}

public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}

/**
* Create schema.
* @throws Exception any exception
*/
public void afterPropertiesSet() throws Exception {
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
jdbcTemplate.execute("CREATE SCHEMA " + schema + " AUTHORIZATION DBA");
}

}



    <bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"
depends-on="hsqlSchemaCreator">
...
</bean>

<bean id="hsqlSchemaCreator" class="com.guident.skills.util.HSQLSchemaCreator">
<property name="dataSource" ref="dataSource" />
<property name="schema" value="MY_SCHEMA" />
</bean>

Monday, November 2, 2009

DDL in Hibarenate Mapping File

If you set Hibernate property "hibernate.hbm2ddl.auto" to "create", Hibernate can automatically create the schema with the mapping files. Great! But what if you have things like triggers? It turns out you can add the specific DDL to element in the mapping file for this purpose.

<hibernate-mapping>
<class>
...
</class>

<database-object>
<create>
[CREATE statement]
</create>
<drop>
[DROP statement]
</drop>
<dialect-scope name="org.hibernate.dialect.HSQLDialect" />
</database-object>
</hibernate-mapping>


The elements restrict the custom CREATE or DROP statements to
a particular set of configured database dialects, which is useful if you’re deploying
on several systems and need different customizations.

Wednesday, October 28, 2009

JUnit4 public setup method in Eclipse

I converted a JUnit test case from JUnit3 to JUnit4 style. This mostly involves not extending TestCase and using annotations such as @Test and @Before etc. JUnit4 in 60 Seconds is an excellent tutorial.

I ran into a problem, however. A test method did not run after the conversion. Eclipse did not throw any error. Its JUnit View simply said "finished in 0 seconds", like it did not run it at all. Eventually I found that the setUp() method was still "protected" as in JUnit3. Everything worked after I changed it to "public".

    /**
* Setup.
*/
@Before
public void setUp() {
// ...
}



Nowhere said that the setup method must be public. It might be an Eclipse thing. Anyway, I just want to note it down here and will revisit it later.

Tuesday, October 27, 2009

Run service command on Linux

If cruisecontrol has been configured as a service on Linux, you can check status/start/stop it with the service command. For example,

service cruisecontrol status

To work withe other services, just replace "cruisecontrol" with other service names.

Checkstyle 5 and maven-checkstyle-plugin 2.3

I installed Eclipse Checkstyle plugin, which uses Checksytle 5. The latest maven-checkstyle-plugin, version 2.3, uses Checkstyle 4.4.

Everything works fine in Eclipse with Checkstyl5 5. Things got tricky when I ran "mvn checkstyle:checkstyle". If I didn't specify custom configuration, it uses the default template from Checkstyle 4.4. So the report will have a lot of false alarm because it did not recognize Java 5 checks. So I specified a custom configuration like this.

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>2.3</version>
<configuration>
<configLocation>checkstyle.xml</configLocation>
</configuration>
</plugin>

The template, checkstyle.xml, is the default "Sun Checks" from Checkstyle 5.0. However, maven threw an error "Unable to instantiate JavadocPackageCheck". According to this post, it is because "You are trying to use a Checkstyle check that was introduced in Checkstyle 5.0. The Checkstyle Plugin currently uses Checkstyle 4.4."

It looks like we have to live with this discrepancy until maven-checkstyle-plugin 2.4, which is based on Checkstyle 5, is released.

Friday, October 16, 2009

Specify initial size for Commons DBCP BasicDatasource

It is fairly easy to setup database pooling with Spring and Commons DBCP BasicDatasource. However, the pool's default initial size is 0 if you look it up in the source code. To change that, specify "initialSize" in your configuration.

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="initialSize">
<value>10</value>
</property>
</bean>

Thursday, October 8, 2009

Get rid of "No runnable methods"

I have a couple of base tests. They are simply for setting up and extension by sub test classes, and have no test methods. Their names are the pattern of "*Tests". This works fine with maven "mvn test". But in Eclipse, when you right click "src/test/java" and "Run as > JUnit test", Eclipse will throw errors "No runnable methods". The trick is to add @Ignore on these base test classes so Eclipse won't bother again. This is of course JUnit 4 style annotation.

Thursday, September 10, 2009

Prefer getters to accessors in Hibernate domain object

I ran into something tricky today. I have a domain object.

public class User {
private String firstName;
private String lastName;

// getters and setters

// a utility method
public String getFullName() {
return this.lastName + ", " + this.firstName;
}
}

Everything looks reasonable except the full name is always "null, null" at runtime. Then I realized Hibernate has lazy loading. "this.lastName" and "this.firstName" are not populated until the getter methods are called. It worked fine after switching to getters.

public String getFullName() {
return this.getLastName() + ", " + this.getFirstName();
}

The encapsulation forces you to user getters outside User class. However, it turns out that in this case, I'd better stick to getters instead of "this." accessor anywhere even inside the User class.

Override equals/hashcode in Hibernate domain object

First of all, make sure that you really need to do that. According to this post,
"You only need to implement equals()/hashCode() on your persistent classes if
- it is a used as a composite primary key class
- instances of that class, loaded in different Hibernate Sessions, are in the same Set (or should be compared)"

When you do, be careful as you might run into a tricky problem. If you were me, you would use Eclipse's wizard to create equals/hashcode, which generates code including the below

if (getClass() != other.getClass()) {
return false;
}

The problem is that Hibernate domain objects are proxies, by Javassist for example. This could return false as one is the domain class and the other is the proxy class. A workaround can be found here.

Again, equals/hashcode are very important and don't take a light decision on overriding them. Use this Hibernate page as reference.

Thursday, August 27, 2009

Hibernate session and Wicket filters

I am working on a web application with Spring, Hibernate and Wicket. I need to define Hibernate session filter in web.xml for "open session in view". But I kept getting Hibernate errors when the app started. The fix, as noted in "Wicket in Action", is to define Hibernate session filter ahead of Wicket filter in web.xml.

Here is a complete web.xml as example.

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">

<display-name>skills</display-name>

<!-- Hibernate session filter -->
<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>singleSession</param-name>
<param-value>true</param-value>
</init-param>
</filter>

<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>


<!--
There are three means to configure Wickets configuration mode and they
are tested in the order given. 1) A system property:
-Dwicket.configuration 2) servlet specific <init-param> 3) context
specific <context-param> The value might be either "development"
(reloading when templates change) or "deployment". If no configuration
is found, "development" is the default.
-->

<filter>
<filter-name>wicket.skills</filter-name>
<filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
<init-param>
<param-name>applicationClassName</param-name>
<param-value>com.guident.skills.web.SkillsWicketApplication</param-value>
</init-param>
<init-param>
<param-name>configuration</param-name>
<param-value>development</param-value>
<!--
change "development" to "deployment" for production
<param-value>deployment</param-value>
-->
</init-param>
</filter>

<filter-mapping>
<filter-name>wicket.skills</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>


<!-- Spring context loader -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:applicationContext.xml
classpath:service.xml
classpath:dao.xml
</param-value>
</context-param>


</web-app>

Create MySQL Triggers

I need to create a trigger in MySQL in the GUI tool Query Browser. However, I kept running into syntax errors. It turns out that I had to specify a delimiter other than ";" like the following.

Delimiter $$

CREATE TRIGGER tr_skill_path BEFORE INSERT ON skill
FOR EACH ROW
BEGIN
DECLARE parent_path CHAR;

IF NEW.parent_skill_id is not null THEN
select path into parent_path from skill where skill_id = NEW.parent_skill_id;
END IF;

IF parent_path is null THEN
SET NEW.path = CAST(NEW.skill_id AS CHAR);
ELSE
SET NEW.path = CONCAT(parent_path, '.', CAST(NEW.skill_id AS CHAR));
END IF;
END$$

Delimiter ;

This made it pass the syntax error. But another error came up:
Access denied; you need the SUPER privilege for this operation

According to MySQL Manual, "SUPER privileges are administrative and can only be granted globally". So it won't work if the grant is only for the schema. More on this later...

Map boolean in Hibernate

How can you map Y/N in database as boolean in Java with Hibernate?

1. Java
private boolean trainingOnly;
// getters and setters

2. DB
training_only VARCHAR(1) DEFAULT 'N',

3. hbm.xml
<property name="trainingOnly" type="yes_no">
<column name="training_only" length="1" />
</property>

Monday, August 24, 2009

Increase Selenium timeout value

I am testing a slow loading page with Selenium (html recorded by Selenium IDE) but it always fails due to timeout. The default timeout value is 300000, i.e., 30 seconds. I know, I know - it is plenty of time and something needs to be done to that page. The question here, however, is how to increase Selenium's timeout to get the test passed.

I can specify the timeout value at the beginning of the html script like

<tr>
<td>setTimeout</td>
<td>600000</td>
<td></td>
</tr>

Now the test passed happily.

Friday, August 21, 2009

Spring test & JUnit

Spring 2.5.x works with JUnit 4.4 but not JUnit 4.5+. You will run into org/junit/Assume$AssumptionViolatedException. This was fixed in Spring 3.0.

http://jira.springframework.org/browse/SPR-5145

Maven test resources

In a Maven project, it is recommended that you keep your test resources in src/test/resources, separate from src/main/resources. However, a lot of times, or most of the time, the resources are pretty much the same, such as service.xml, dao.xml, log4j.properties etc. When you work on a new DAO in TDD fashion, you would add the definition in src/test/dao.xml first and copy it to src/main/dao.xml once it works as expected. It becomes a hassle to maintain both places. I would say why not share the main resources with test. You can do it literally this way: tell test to use main as resouces.

<testResources>
<testResource>
<filtering>false</filtering>
<directory>src/mail/resources</directory>
</testResource>
</testResources>

Spring ContextLoaderListener ClassNotFoundException

I ran a Java web application with Maven, Tomcat in Eclipse. When the application started, Eclipse console has the exception:
java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener

Of course, I did not forget to define Spring dependency in Maven pom.xml. But when I checked the deployment at
ECLIPSE_WORKSPACE\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\APPLICATION\WEB-INF\lib
, there was no Jar indeed. So it looked like something went wrong with Eclipse/Tomcat/Maven deployment.

I did a couple of things to make it work.
1. Get rid of duplicated classes. For example, the dependency on spring-aspects also brings in spring-beans and spring-core, which are already part of spring dependency. Tip: use "mvn dependency:tree" to the dependency tree. So I need to exclcude it by
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>2.5.6</version>
<!-- exclude spring-beans which is part of spring-2.5.6.jar -->
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</exclusion>
</exclusions>
</dependency>
2. Right click project > Maven > Update Project Configuration. Disable and re-enable Maven dependency management if necessary.

Now I found all the required jars in the right place. I started the application and no error!

This seems to be a glitch with Eclipse Maven plugin. I need to keep an eye on it.

Thursday, July 30, 2009

Search Documentum including old version

A document in documentum is versioned. By default, documentum only searches the current version of documents. To include old version, add (all) in the query like this example.

select * from opp_assessment(all)
where ref_doc_num = '0919999980028b06'

Wednesday, July 22, 2009

Escape in JSTL XML tag

In JSTL XML tag, if the data has characters like "<", it will be escaped by default. To turn it off, set escapeXml to false.

<x:out select="$n/STATUS" escapeXml="false" />

Friday, June 26, 2009

Remove from Hibernate Set

Suppose you have one-to-many bi-directional mapping between Category and Item.

public class Category {
Set items;
}

public class Item {
Category category;
}

To remove an item from Category, you need to do this

category.getItems.remove(item1);
delete(item1); // delete() is from Hibernate API

The first line takes out the relationship while the second one deletes it.

Wednesday, June 24, 2009

Use log4j in JSP

http://www.mobilefish.com/developer/log4j/log4j_quickguide_jsp.html

Use the following section in pom.xml to declare the dependency in maven
<dependency>
<groupId>taglibs</groupId>
<artifactId>log</artifactId>
<version>1.0</version>
</dependency>

Monday, June 22, 2009

Format date in Hibernate Mapping

<property name="birthday" type="date" formula="trunc(BIRTHDAY)">
<column length="20" name="BIRTHDAY"/>
</property>

Tuesday, June 9, 2009

Update jquery tablesorter cache

jquery table sorter caches the data. You need to update the cache after removing table rows. Otherwise, the removed rows will show up again. Here is how to update the cache.

$('#myTable').trigger("update");

Thursday, May 21, 2009

OAS JVM settings

OAS_HOME/j2ee/oc4j_opmn.xml hasJVM settings for OAS.

OAS configuration

We have a VM host1 which installs OAS. Then it is replicated as host2. To start OAS on host2, we need to change some configuration.
  1. Make sure the host name is host2 with "ipconfig /all".
  2. Change the host name to new one in OAS_HOME/config/ias.properties, OAS_HOME/opmn/conf/opmn.xml
Now start OAS and try login to http://host2/em. If you are redirected to http://host1/em, it is probably OAS thinks this is a cluster installation. You will get the error message said
"You have been logged off and redirected to the canonical server name."
In this case, you need to change OAS_HOME/Apache/Apache/conf/httpd.conf and set
UseCanonicalName Off

Tuesday, May 19, 2009

Spring mvc bind select

Here is an example to use spring:bind to bind HTML select. Note the hidden input at the end is very important to spring bind.


<spring:bind path="labelChanges.details">
<select id="detailFilter" name="${status.expression}" multiple="multiple" class="searchFilter">
<c:forEach var="item" items="${labelChangeMitigationDetails}">
<c:forEach items="${status.value}" var="currentItem">
<c:if test="${currentItem == item.value}">
<c:set var="selected" value="true"/>
</c:if>
</c:forEach>

<option value="${item.value}"
<c:if test="${selected}">selected="selected"</c:if>>
<c:out value="${item.key}" />
</option>

<c:remove var="selected"/>
</c:forEach>
</select>
</spring:bind>
<input type="hidden" name="_details" value="1"/>


Another options is to use form:select


<form:select id="statusFilter" cssClass="searchFilter"
path="statuses"
items="${labelChangeStatuses}"
itemValue="lcStatusRefSeq"
itemLabel="lcStatusName"
multiple="true" />
</td>

Friday, May 15, 2009

How to further filter "this" in jquery?

Suppose this is the HTML.

You can use $('div') to get it. You can refer to it by "this". What if you want to get "img"? How do you apply selector on "this"?

The jQuery constructor accepts a 2nd parameter which can be used to override the context of the selection.
$("img", this);

Wednesday, May 13, 2009

form submission url

When you load the form, the url is "myaction.htm?id=123". You want to keep the url when the form is submitted. All you need to do is to define form action as "action=myaction.htm?id=123". Note that you cannot have another "id" field in the form. If you use Spring bind, it might lead to binding errors.

Return ModelAndView in Spring mvc onSubmit()

You need to return ModelAndView In Spring's SimpleFormController onSubmit() method. There are a few options here.

1. Redirect to another page
return new ModelAndView(new RedirectView("anotherPage.htm");

2. Return to the same form
return new ModelAndView(getSuccessView());

As long as you return "new" ModelAndView, you will have to go through formBackingObject() method.

3. Return to the same form but bypass formBackingObject() method
return showForm(request, errors, getSuccessView());
showForm() method calls and carries all reference data.


Tuesday, May 12, 2009

jquery starts with selector

"^=" is the operator for "starts with" in jquery. For example, the following finds all inputs whose names starts with "abc".

$("input:[name^='abc']")


Find all checked checkbox input with the css class name "non-draft=status"

$('input:checkbox.non-draft-status:checked')

Find all of td's children whose class is "data4Sort". Note children() only gives you the immediate children while find() goes deeper.

$('td').find('.data4Sort')

Spring bind collection to checkbox

Here is an example in JSP to bind a collection as checkboxes with spring form:checkbox.

<c:forEach varStatus="status" var="product" items="${command.products}">
<form:checkbox path="products[${status.index}].productId" value="${product.id}" />
</c:foreach>

Note the command will always have the collection "products". However, the selected ones - the ones with checkbox checked, will have valid "id" values. This is the way to tell which ones are selected.

Friday, May 8, 2009

Customize Hibernate Mapping Strategy

You can use Hibernate reverse engineering tools to create mapping files and Java classes. However, the default mapping may not always fit your need. For example, it maps table primary key to BigDecimal and uses "assigned" generator. You can add customization in hibernate.reveng.xml to change that. Here is an example of how to map PK to Integer with sequence generator. You can also define "type-mapping" for global type mappings.

Tuesday, May 5, 2009

Hql with collections and named parameters

An example of how you can use hql to query collections and names parameters. The bold part is for collections. The find() method is from Spring HibernateTemplate.

String query = "select cp from CaseProduct cp, LcLabelChange lc "
+ " where cp.puid=? "
+ " and lc member of cp.labelChanges "
+ " and lc.lcMitigation.caseIngredient.caseIngredientSeq=?";
Object[] params = new Object[]{puid, caseIngredientId};
List list = find(query, params);

Hibernate mapping for trigger populated columns

Suppose you have table columns whose values are populated by triggers. For example, createdBy, updatedBy, createdDate, & updatedDate. The following Hibernate mapping indicates that these columns are managed by database. The mapping is also "trigger friendly" - Hibernate will retrieve the values automatically. There is no need for an extra explicit SELECT.

Monday, April 20, 2009

JavaScript Method Overloading

JavaScript has some OO features, but it does not really support method overloading. If you defined two methods with the same name but different input parameters, it won't throw any syntax error. However, it always calls the second one at runtime. A reference is here.

Sunday, April 19, 2009

Closed Connection with getMetaData in Spring StoredProcedure

When using Spring's StoredProcedure, it runs into the error "Closed Connection" with Connection.getMetaData().

Error while extracting database product name - falling back to empty error codes
org.springframework.jdbc.support.MetaDataAccessException: Error while extracting DatabaseMetaData; nested exception is java.sql.SQLException: Closed Connection
java.sql.SQLException: Closed Connection


This might have something to do with the networks ports. A detailed description is here. This needs to be revisited.

Wednesday, April 15, 2009

Bind a list to HTML select with Spring

Let's say you have a list of objects that you want to bind as HTML SELECT in JSP. You need to populate the list with data in referenceData(). Note it has to be a list of objects with getters and setters for properties (or Spring PropertyValue object). Next you can add the following code in JSP.



"aProperty" here is the name of the property in the command object that you want to bind the selected option to.

Tuesday, April 14, 2009

Debug JavaScript in IE with Microsoft Script Debugger

You can use Microsoft Script Debugger to debug JavaScript in IE. This blog has details about its installation and setting up IE. When a JavaScript error occurs in IE, you can click OK to debug. It will then open Microsoft Script Debugger and highlight where the error is.

Maintain the order of List in Spring Bind

In most cases, one-to-many is mapped as Set in Hibernate. Set is not ordered. If a domain object has Set, Set is converted to List in DTO to bind it with Spring. If that's the case, it is very important to maintain the order. Here is a use case. A Spring form controller is set to sessionForm= false and the DTO is read in formBackingObject().

  1. A user comes to the form the first time. formBackingObject() is called. Domain object is read. DTO is created. Set is converted to List.
  2. Form is rendered. Elemenets in List is created in HTML.
  3. User fills out data and submits.
  4. Since sessionForm is false, formBackingObject() is called again BEFORE onSubmit(). Again, Domain object is read. DTO is created. Set is converted to List. However, please note that when the domain object is read this time, the order of elements in Set could be different from Step 1. Then the order of elements in List is different the ones in Step 1.
  5. Binder.bind() happens. Bind is still binding the List data according to the order in Step 1. But the actual order of List data is as in Step 4. This means that the binding binds the data of 1st element to that of the 3rd element, for example.
  6. Now it comes to onSubmit(). The DTO's list data has the wrong binding. Once this data is processed at the service/DAO, it could run into all kinds of errors/bugs.

To fix this problem, we need to avoid the seond reading in Step 4. This can be done by setting sessionForm=true. Or if it has to be read, we can add "sort" or "order by" in Hibernate mapping for the Set to force it to maintain a consistent order.

Bind indexed properties in Spring

You can use sping:bind to bind indexed properties. This only works with ordered collection such as List, but not Set.



Here are a few things to note.
  1. The syntax of "path=ingredientDtos[${rowId.index}].baselineDate" - this tells Spring to bind these to a list. If you use "c:out" instead of "form:input" or "form:hidden", then the field will not be submitted and bound
  2. Only the fields listed here in this syntax are submitted and bound. For example, if ingredient has a property called "company" and it is not added here with form:input or form:hidden. Then you will find the property is null in onSubmit(). So the object might miss properties unless they are all listed and bound.

Monday, April 13, 2009

Maven help plugin

Not all maven plugins have good documentation. A lot of times I wonder how to run or use a plugin correctly. The maven "help" plugin is a great help here. It shows the goals and usage for a particular plugin. For example, run the command below to find out how to run axis2 aar plugin.

mvn help:describe -DgroupId=org.apache.axis2 -DartifactId=axis2-aar-maven-plugin -Dversion=1.4.1

Friday, April 10, 2009

Log Hibernate SQL Statements and Parameter Values

It is important to see Hibernate SQL Statements and the binding values for parameters in log to troubleshoot and debug. A nice trick here shows how to do it in log4j.

Basically, it is done by adding the following two lines in log4j.properties.
log4j.category.org.hibernate.SQL=DEBUG
log4j.category.org.hibernate.type=TRACE

You also need to change the appender Threshold, for example, CONSOLE.
log4j.appender.CONSOLE.Threshold=TRACE

Thursday, April 9, 2009

Open-Session-In-View



Servlet 2.3 Filter that binds a Hibernate Session to the thread for the entire processing of the request. Intended for the "Open Session in View" pattern, i.e. to allow for lazy loading in web views despite the original transactions already being completed.

NOTE: This filter will by default not flush the Hibernate Session, with the flush mode set to FlushMode.NEVER. It assumes to be used in combination with service layer transactions that care for the flushing: The active transaction manager will temporarily change the flush mode to FlushMode.AUTO during a read-write transaction, with the flush mode reset to FlushMode.NEVER at the end of each transaction. If you intend to use this filter without transactions, consider changing the default flush mode (through the "flushMode" property).

Hibernate schema definition and Oracle public synonym

Make sure that you don't specify schema in Hibernate mappings if you have public synonym defined for tables in Oracle.

Here is the setup. I had a table MY_TABLE mapped in MyTable.hbm.xml. In the database, a public synonym "MyTable" is created for MY_TABLE. I also had two schema definitions in Hiberante. One is the default schema in Spring config.



The second is in MyTable.hbm.xml


At runtime, Hibernate has problem resolving and working on the right table. It worked after schema definitions were removed from both places and left the resolution to Oracle.

Tuesday, April 7, 2009

What is "String..."?

I saw "String..." in a method signature like this. What exactly is "String..."?
public void aMethod(String... args) {
...
}

"..." here is actually sort of a shortcut to Array. So the code above is pretty much the same as
public void aMethod(String[] args) {
...
}

However, when calling aMethod, you can do
aMethod("s1", "s2, "s3");
instead of
aMethod(new String[]{"s1", "s2", "s3"});
That is convenient. This can be used for any types of Array, such as "Integer...".

Monday, April 6, 2009

Loal artifacts on Artifactory

Artifactory is a maven repository server. In addition to link to external repository servers, it can also host artifacts itself. These artifacts can be found at xxx-local when you browse Artifactory, for example, libs-releases-local and libs-snapshots-local. You can export them in admin console.

Thursday, April 2, 2009

Autowire datasource by name for Spring test base class

Suppose you extends AbstractTransactionalJUnit4SpringContextTests but you have multiple datasource beans. When the context is loaded, Spring will complain that it could not setDatasource() for AbstractTransactionalJUnit4SpringContext because there is more than one bean with the type.

The solution is described here in Spring Docs.

If you are extending from a Spring-provided test base class that happens to use @Autowired on one of its setters methods, you might have multiple beans of the affected type defined in your application context: e.g. multiple DataSource beans. In such a case, you may override the setter and use the @Qualifier annotation to indicate a specific target bean as follows:

...
@Override @Autowired
public void setDataSource(@Qualifier("myDataSource") DataSource dataSource) {
super.setDataSource(dataSource);
}
...

Call stored procedures or functions in Spring

A easy way to call stored procedure or function is to use Spring's SimpleJdbcCall class. It wraps up some convenient features. Most likely, you only need to provide in/out parameters. It uses JdbcTemplte internally.

Here is an example to call stored procedure.
SimpleJdbcCall caller = new SimpleJdbcCall(getDataSource())
.withCatalogName("PKG_OPPIN")
.withFunctionName("pc_unsubmit_from_rr");

SqlParameterSource params = new MapSqlParameterSource()
.addValue("p_case_seq", caseSeq)
.addValue("p_task_seq", taskSeq);

// this sp has no return
caller.execute(params);

Here is an example to call function.
SimpleJdbcCall caller = new SimpleJdbcCall(getDataSource())
.withCatalogName("PKG_OPPIN")
.withFunctionName("fn_get_bean_target_date");

MapSqlParameterSource params = new MapSqlParameterSource()
.addValue("p_dpkg_seq", dataPackageNumber);

Date beanTargetDate = caller.executeFunction(Date.class, params);

return beanTargetDate;


To avoid a call to get metadata, you can declare all parameter explicitly. Here is an example.

SimpleJdbcCall caller = new SimpleJdbcCall(getDataSource())
.withCatalogName("PKG_REG_REVIEW")
.withFunctionName("fn_get_task_complete_date")
.withoutProcedureColumnMetaDataAccess()
.declareParameters(
new SqlOutParameter("v_maxdate", Types.DATE),
new SqlParameter("p_case_seq", Types.INTEGER),
new SqlParameter("p_task_seq", Types.INTEGER)
);

MapSqlParameterSource params = new MapSqlParameterSource()
.addValue("p_task_seq", taskSeq)
.addValue("p_case_seq", caseSeq);

Date taskCompletionDate = caller.executeFunction(Date.class, params);

return taskCompletionDate;

The use of withoutProcedureColumnMetaDataAccess() disables metadata reading. Note that the order matters in declareParameters() - it should match exactly the order of the parameters when the procedure/function is called. Another thing to note is that you don't need to use useInParameters() with withoutProcedureColumnMetaDataAccess() because it is only for filtering the metadata.

Another way to call sp/function is to use Spring's StoredProcedure class. But you will need to create a sub-class for it since StoredProcedure is abstract. Here is an example.

MyStoredFunction fn = new MyStoredFunction(getJdbcTemplate(),
"PKG_REG_REVIEW.fn_get_task_complete_date");
fn.declareParameter(new SqlOutParameter("v_maxdate", Types.DATE));
fn.declareParameter(new SqlParameter("p_case_seq", Types.INTEGER));
fn.declareParameter(new SqlParameter("p_task_seq", Types.INTEGER));
fn.compile();

Map params = new HashMap();
params.put("p_case_seq", caseSeq);
params.put("p_task_seq", taskSeq);

Map result = fn.execute(params);
Date taskCompletionDate = (Date) result.get("v_maxdate");
The execute() method always return a Map. You need to get and cast to get the returned data.

Execute stored procedure or function in TOAD

Question:
How do you execute a stored procedure or function and display the result in TOAD?

Answer:
Navigate to the sp or function in schema browser and highlight it. There is a thunder button "Execute Procedure" up there. Click on it to bring up the dialog where you can provide input parameters.

To see output, you need to do things. First, . First, open a output window by View > DBMS Ouput. Second, in the execute dialog, click "Output Options" link and check "Print OUT arguments/RETURN values to DBMS Output". Now the result will be disaplyed in the DBMS Ouput window after you click OK to execute the sp or function.

Wednesday, April 1, 2009

HibernateException: connection proxy not usable after transaction completion

Problem:
Some DAO methods acquire connections by
getSession().connection()
before calling stored procedures. Then they close the connection explicitly with
JdbcUtils.closeConnection()
Then the application throws "HibernateException: connection proxy not usable after transaction completion" from time to time.

Solution:
As described in Hibernate API, "if the session is using aggressive collection release (as in a CMT environment), it is the application's responsibility to close the connection returned by this call. Otherwise, the application should not close the connection". So in this case, it is fixed by remving the code to close connections.

Saturday, March 28, 2009

Check wasNull with JDBC CallableStatement

Suppose you have a CallableStatement which calls a database function and returns an integer. You would register the out parameter by
cs.registerOutParameter(1, Types.Integer);
cs.execute();

Let's say you want to check if NULL is returned as below.
Integer result = cs.getInt(1);
if (result == null) {
// NULL
}

This is wrong because result will be 0 (zero), instead of null, if NULL is returned from the database function. This is documented here.

The right way to check is to use wasNull.
Integer result = cs.getInt(1);
if (cs.wasNull) {
// NULL
}