X
  • Monday, April 12, 2010

Bergen & iBatis on the NetBeans Platform

By: Geertjan Wielenga | Product Manager
Toni and I are visiting the Institute of Marine Research in Bergen, Norway, where a set of heavily data-centric applications (i.e., for processing data coming back from research cruises all over the world) are being integrated into a consolidated application on the NetBeans Platform.

A snapshot of the group to give a quick impression:

They're strongly in favor of using free & open-source solutions, of which the NetBeans Platform is obviously one. (In several cases, we're introducing them to NetBeans IDE for the first time, since several didn't know about the lightbulb hints in the IDE, while others hadn't used the Matisse GUI Builder before.) Another one is iBatis, which I had heard of but never used before. This gave me sufficient info and now I have a small CRUD (well, only "R" at this point) sample on the NetBeans Platform via iBatis (i.e., no JPA is being used, only a Derby database and iBatis XML files, with iBatis code in the TopComponent):

To give a quick intro to iBatis in the context of the NetBeans Platform, here's a screenshot of the application structure, followed by a brief description of the highlighted nodes below:

The highlighted files above:

  • Customer API. An API module that exposes two classes (generated in the IDE via the wizard, after which I deleted all the JPA annotations, leaving me with two POJOs representing rows in a database).
  • CustomerViewer. A module that provides the window that you see in the application, together with the two XML files typical to iBatis applications:
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE sqlMapConfig PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"
    "http://www.ibatis.com/dtd/sql-map-config-2.dtd">
    <sqlMapConfig>
    <settings cacheModelsEnabled="true" enhancementEnabled="true"
    lazyLoadingEnabled="true" maxRequests="32" maxSessions="10" maxTransactions="5"
    useStatementNamespaces="false" />
    <transactionManager type="JDBC">
    <dataSource type="SIMPLE">
    <property name="JDBC.ConnectionURL" value="jdbc:derby://localhost:1527/sample"/>
    <property name="JDBC.Password" value="app"/>
    <property name="JDBC.Driver" value="org.apache.derby.jdbc.ClientDriver"/>
    <property name="JDBC.Username" value="app"/>
    </dataSource>
    </transactionManager>
    <sqlMap resource="Customer.xml" />
    </sqlMapConfig>
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
    "http://ibatis.apache.org/dtd/sql-map-2.dtd">
    <sqlMap namespace="Customer">
    <typeAlias alias="customer" type="org.customer.api.Customer"/>
    <select id="getAll" resultClass="customer">
    select \* from customer
    </select>
    </sqlMap>

    The above two do the same as persistence.xml in JPA, i.e., make a connection to the (in this case) Sample database in NetBeans IDE and retrieve the requested data.


  • DerbyClientLib. A single JAR (derbyclient.jar from the JDK) wrapped into a module and made available to the iBatis module.
  • iBatisLib. Two JARs from iBatis wrapped into a module and made available to the CustomerViewer module.

And how is the data retrieved by iBatis and shown in the window? Like this, in the TopComponent:

public CustomerTopComponent() {
Reader reader = null;
try {
initComponents();
setName(NbBundle.getMessage(CustomerTopComponent.class, "CTL_CustomerTopComponent"));
setToolTipText(NbBundle.getMessage(CustomerTopComponent.class, "HINT_CustomerTopComponent"));
add(new BeanTreeView(), BorderLayout.CENTER);reader = Resources.getResourceAsReader("SqlMapConfig.xml");
SqlMapClient sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);
List<Customer> customers = (List<Customer>) sqlMap.queryForList("getAll", null);
//And here we pass the retrieved customers into the factory that creates nodes:

em.setRootContext(new AbstractNode(Children.create(new CustomerChildFactory(customers), true)));
em.getRootContext().setDisplayName("Customers");
} catch (SQLException ex) {
Exceptions.printStackTrace(ex);
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
} finally {
try {
reader.close();
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
}
}
associateLookup(ExplorerUtils.createLookup(em, getActionMap()));
}

Here's the 'CustomerChildFactory' you see referenced above:

import java.beans.IntrospectionException;
import java.util.List;
import org.customer.api.Customer;
import org.openide.nodes.BeanNode;
import org.openide.nodes.ChildFactory;
import org.openide.nodes.Node;
import org.openide.util.Exceptions;
public class CustomerChildFactory extends ChildFactory<Customer> {
private final List<Customer> customers;
CustomerChildFactory(List<Customer> customers) {
this.customers = customers;
}
@Override
protected boolean createKeys(List<Customer> list) {
list.addAll(customers);
return true;
}
@Override
protected Node createNodeForKey(Customer key) {
try {
return new BeanNode(key);
} catch (IntrospectionException ex) {
Exceptions.printStackTrace(ex);
}
return null;
}
}

And that's all. A simple example of iBatis usage on the NetBeans Platform. But I wonder why/when iBatis would be used rather than JPA?

Join the discussion

Comments ( 3 )
  • Jim Christie Monday, April 12, 2010

    We have found iBatis to be the cleanest solution for integrating with legacy databases (where the structure of the database has evolved independently from an individual application). iBatis is particularly useful if your application code has significant interaction with stored procedures.


  • Trond Westg&aring;rd Sunday, April 18, 2010

    Jim,

    how beautifully put. This is precisely the reason why we have choosen iBatis two years ago. I read two chapters in a Spring Framework textbook. One chapter was about Hibernate and one about iBatis and then we took the decision. Both Hibernate and iBatis are strong tools of course and my impression is that Hibernate has a larger number of users.


  • guest Friday, April 24, 2015

    Unfortunately, ibatis/mybatis leads to objects that are nothing but empty. In other words they are just structs in the old C/C++ world. I have seen an application declare an object and never ever use a set method. You scratch your head and then it becomes obvious that inserts and updates do it for you behind the scenes. I'd not recommend mybatis since it will lead to the same maintenance nightmare as of a legacy application. Better redesign the database and build it right using JPA.


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.Captcha