Saturday 12 December 2009

Spring + ibatis: calling a sql procedure

This post is a sample of a procedure call from ibatis, when we're under the spring influence!

This is the ibator generator xml. Used with the eclipse plugin.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE ibatorConfiguration PUBLIC "-//Apache Software Foundation//DTD Apache iBATIS Ibator Configuration 1.0//EN" "http://ibatis.apache.org/dtd/ibator-config_1_0.dtd" >
<ibatorConfiguration >
 <classPathEntry location="C:\eclipse\extra\BDD\SQLServer\sqljdbc_2.0\esn\sqljdbc4.jar" />
 <ibatorContext id="test" >
     <jdbcConnection driverClass="com.microsoft.sqlserver.jdbc.SQLServerDriver" connectionURL="jdbc:sqlserver://...:1433;databaseName=...." userId="..." password="..."/>
     <javaModelGenerator targetPackage="es.test.model.WebProd" targetProject="test.negocio" />
     <sqlMapGenerator targetPackage="es.test.dao.WebProd.sqlMap" targetProject="test.negocio" />
 <daoGenerator targetPackage="es.test.dao.WebProd" targetProject="test.negocio" type="SPRING" />
 <table schema="dbo" catalog="WebProd" tableName="aliasCuentas">
   <property name="useActualColumnNames" value="true"/>
 </table>    
  </ibatorContext>
</ibatorConfiguration>

To the generated code of ibator, just add the next items:


In WebProd_dbo_aliasCuentas_SqlMap.xml:
<parameterMap id="getAccountsCall" class="map">
 <parameter property="titular" jdbcType="VARCHAR" javaType="java.lang.String" mode="IN"/>
 <parameter property="permiso" jdbcType="VARCHAR" javaType="java.lang.String" mode="IN"/>
</parameterMap>
<resultMap id="cuentaAlias" class="es.test.model.WebProd.Aliascuentas">
 <result property="aliasCuenta" column="aliasCuenta" />
 <result property="idCuenta" column="idCuenta" />
</resultMap>
<procedure id="getAccounts" resultMap="cuentaAlias" parameterMap="getAccountsCall">
 {call WebProd.dbo.sp_web_getCuenstasUsuarioAlias(?, ?)}
</procedure>


In AliascuentasDAO:
List<es.test.model.WebProd.Aliascuentas> selectCuentas(Map example);


In AliascuentasDAOImpl:
public List<es.test.model.WebProd.Aliascuentas> selectCuentas(Map example) {
 List<es.test.model.WebProd.Aliascuentas> list = getSqlMapClientTemplate().queryForList("WebProd_dbo_aliasCuentas.getAccounts", example);
 return list;
}


Now, the configurations files of spring and the java source of the call.


In applicationContext*.xml:
<bean id="aliascuentasDAO" class="es.test.dao.WebProd.AliascuentasDAOImpl">
 <property name="sqlMapClient">
  <ref bean="sqlMapWebProd"/>
 </property>
</bean>
<bean id="aliasServicio" class="es.test.miGestion.administracionDatos.service.AliasCuentasServiceImpl">
 <property name="aliascuentasDAO">
  <ref bean="aliascuentasDAO"/>
 </property>
</bean>

And finally the AliasCuentasServiceImpl.java:
public List<Aliascuentas> getCuentas(String usuario) {
 log.debug("getCuentas: inicio. usuario:" + usuario);
 List<Aliascuentas> cuentasList;

 Map<String, String> map = new HashMap<String, String>();
 map.put("titular", usuario);
 map.put("permiso", "Consultas");
 cuentasList = aliascuentasDAO.selectCuentas(map);
 log.debug("getCuentas: fin");
 return cuentasList;
}

That's all!.

Friday 13 November 2009

Ajax Cross-domain

We have a web project that the 90% of the data it's taken from an outer domain. As the client forced us to make the queries directly to the other domain, we decided to use flXHR.

flXHR is a *client-based* cross-browser, XHR-compatible tool for cross-domain Ajax (Flash) communication.”

As we used jquery for build the tables, the right solution seems to use the flXHR jQuery plugin. And all seems right while we were testing in firefox and IE 8, but when we began to test it in IE7 we saw that "sometimes" after the refresh of the page... we had the CPU up to 100% and the IE7 blocked.

After a refactorization and finally a total simplification of the page, we saw that the only way to use safely flXHR was putting the include of the flXHR.js file at the end of the page, or at least the last one of all the js includes of the page.

The next simple example ends with 100% CPU if you refresh the page quickly so many times (source):


Sunday 4 October 2009

Developing Portlets using Eclipse. Part II


As I told you, the architecture that I use for these post, has iBATIS for it's persistence layer.

The main reason for use this framework was that iBatis give you the flexibility of write your own optimized sql code, and an easy way to call directly to a sql procedure. Not to mention, the existence of iBator, the code generator for iBatis :)

Spring will be a pivotal piece for the application, the reason for use of this framework it's as simple as I want to sleep as a baby. Some of the things that I want accomplish with spring is to have transparency over my data-source connection, jms..,, to make uncouple implementations from each other...

Well, the first interaction between ibatis and spring it's done in the configuration files, the next example show you how to make a configuration that also makes the application container independent.

Extract from applicationContext.xml:
<!-- obtain datasource  -->   
<jee:jndi-lookup id="dataSourceWebProd" jndi-name="jdbc/webProd" cache="true" resource-ref="true" lookup-on-startup="false" proxy-interface="javax.sql.DataSource"/>

<!-- map iBatis to datasource  -->   
<bean id="sqlMapBaseWeb" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
 <property name="configLocation"><value>classpath:/config/sqlmap-configWebProd.xml</value></property>
 <property name="dataSource"><ref bean="dataSourceWebProd" /></property>
</bean> 

<bean id="aliascuentasDAO" class="es.struts2PortletTemplate.dao.WebProd.AliascuentasDAOImpl">
 <property name="sqlMapClient">
  <ref bean="sqlMapWebProd"/>
 </property>
</bean>
<bean id="informesServicio" class="es.struts2PortletTemplate.miGestion.informes.service.InformesServiceImpl">
 <property name="aliascuentasDAO">
  <ref bean="aliascuentasDAO"/>
 </property>
</bean>

sqlmap-configWebProd.xml:
<settings cachemodelsenabled="true" enhancementenabled="true" usestatementnamespaces="true">
    <sqlmap resource="es/struts2PortletTemplate/dao/WebProd/sqlMap/WebProd_dbo_aliasCuentas_SqlMap.xml">
</sqlmap></settings>

And of course, you may well decide to use the Spring Framework's declarative transactions offer...
<bean id="txManagerWebProd" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
 <property name="dataSource" ref="dataSourceWebProd"/>
</bean>
<tx:advice id="txAdviceWebProd" transaction-manager="txManagerWebProd">
 <tx:attributes>
  <tx:method name="get*" read-only="true"/>
  <tx:method name="find*" read-only="true"/>
  <tx:method name="view*" read-only="true"/>
  <tx:method name="save*" propagation="REQUIRED"/>
  <tx:method name="*" propagation="REQUIRED"/>
 </tx:attributes>
</tx:advice>

Saturday 12 September 2009

Easy developing and debuging portlets with eclipse WTP

This little entry is just to show you how quickly I have my new environment up and running. As I told you in my firt post, I develop the portlets with:

Eclipse with WTP
JetSpeed 2.2.0

And I will use Struts2 (Struts 2.1.7) portltes (JSR 168)...

The next log it's from a start up of the jetSpeed in debug mode.

INFO: JetspeedContainerServlet: attemping to start Portlet Application at: /Struts2PortletTemplate
12-Sep-2009 01:49:02 org.apache.catalina.core.ApplicationContext log
INFO: JetspeedContainerServlet: started Portlet Application at: /Struts2PortletTemplate
12-Sep-2009 01:49:03 org.apache.catalina.core.ApplicationContext log
INFO: Initializing Spring root WebApplicationContext
12-Sep-2009 01:49:04 org.apache.catalina.core.ApplicationContext log
INFO: JetspeedContainerServlet: starting initialization of Portlet Application at: j2-admin
JetspeedContainerServlet: starting initialization of Portlet Application at: j2-admin12-Sep-2009 01:49:04 org.apache.catalina.core.ApplicationContext log
INFO: JetspeedContainerServlet: Could not yet start portlet application at: j2-admin. Starting back ground thread to start when the portal comes online.

12-Sep-2009 01:49:04 org.apache.catalina.core.ApplicationContext log
INFO: JetspeedContainerServlet: initialization done for Portlet Application at: j2-admin
JetspeedContainerServlet: initialization done for Portlet Application at: j2-admin
12-Sep-2009 01:49:04 org.apache.catalina.core.ApplicationContext log
INFO: JetspeedContainerServlet: attemping to start Portlet Application at: /j2-admin
12-Sep-2009 01:49:05 org.apache.coyote.http11.Http11Protocol start
INFO: Starting Coyote HTTP/1.1 on http-8080
12-Sep-2009 01:49:05 org.apache.jk.common.ChannelSocket init
INFO: JK: ajp13 listening on /0.0.0.0:8009
12-Sep-2009 01:49:05 org.apache.jk.server.JkMain start
INFO: Jk running ID=0 time=0/267  config=null
12-Sep-2009 01:49:05 org.apache.catalina.startup.Catalina start
INFO: Server startup in 14474 ms
12-Sep-2009 01:49:06 org.apache.catalina.core.ApplicationContext log
INFO: JetspeedContainerServlet: started Portlet Application at: /j2-admin


It takes only 14474 ms
can you do this with websphere?? ;)

Wednesday 19 August 2009

Developing Portlets using Eclipse. Part I

On this entries I will show you how to develop portlets, create and debug portlets, in Eclipse with the WTP plugin and Jetspeed-2 . Lately I will deploy those portlets for the Websphere Portal 6.1.

Some frameworks that I will use:
The environmentLocations that I use to use with Linux:
  • /data/eclipse/eclipseWTP -> here's the eclipse.exe
  • /data/eclipse/eXtra/Jetspeed-2.2.0 -> for Jetspeed
  • /data/workspace/groupA -> for development
Locations that I use to use with Windows:
  • c:\eclipse\eclipseWTP -> here's the eclipse.exe
  • c:\eclipse\eXtra\Jetspeed-2.2.0 -> for Jetspeed
  • c:\apps\workspace\groupA -> for developement
OK, now it's time to configure our eclipse:
  • Add a new server runtime. In eclipse "Preferences/Sever/Runtime Enviroment", add "Apache Tomcat v6.0" and use the installation of the Jetspeed as "Tomcat installation directory "/data/eclipse/eXtra/Jetspeed-2.2.0".
  • Configure the new server. Here's the most important thing, just after we create the new server, we have to edit the server configuration and then "use Tomcat installation" (the default could be "use workspace") and change the "deploy path" to point where we had the "webapps" in our Jetspeed installation "/data/eclipse/eXtra/Jetspeed-2.2.0/webapps". Also we have to change the timeout to start the server.

The portlet

In eclipse, create a new Dynamic Web Project with target runtime: "Jetspeed 2.2.0". Project name: Struts2PortletTemplate :)
OK, now change the project properties, in "Java build path"... I like this "Struts2PortletTemplate/WebContent/WEB-INF/classes" as the output folder.

This will be the web.xml:

Tuesday 16 June 2009

MDA: the practical uml with Acceleo

Maybe one of the best things of the MDA is that with a good template you can have all the test classes builded from just one click. Not to comment, the fact that the project will allways keep well documented with detailed uml :)



I used topcased as modeling tool and Acceleo as code generator.

It's very easy to extend the JEE Hibernate/Struts module of Acceleo.

As a starting point, this module ships with a basic generation of junit-unit and html-unit components. But it's not hard to extend these components for generate more precise classes for testing. That will save us much of the tedious task of generating test classes

Here is a sample:

<%--
  sso 03-2008
--%>
<%
metamodel http://www.eclipse.org/uml2/2.0.0/UML
import es.sso.uml21.common.common
import es.sso.uml21.common.specifics
import es.sso.uml21.common.dataTypes
import es.sso.uml21.common.structure
import es.sso.uml21.common.services.StringServices
import es.sso.uml21.common.services.ListServices
import es.sso.uml21.common.services.Uml2Services
%>


<%script type="Class" name="fullFilePath"%>
<%if (hasStereotype(getProperty("Entity"))){%>
/<%daoTestPackage.toPath()%>/<%name%>DaoTest.java
<%}%>

<%script type="Class" name="generate" file="<%fullFilePath%>"%>
package <%daoTestPackage%>;

// <%startUserCode%> for import
<%if (attribute.select("type.name == 'Date'")){%>
import java.util.Date;
<%}%>

import junit.framework.Assert;
import junit.framework.TestCase;

import java.sql.SQLException;

import org.apache.commons.beanutils.DynaBean;

import com.mockrunner.jdbc.StatementResultSetHandler;
import com.mockrunner.mock.jdbc.MockResultSet;

import es.lacaixa.intranet.commons.beanutils.LazyDynaBean;
import es.lacaixa.intranet.test.BasicDAOTest;
import <%daoPackage%>.<%name%>Dao;

// <%endUserCode%> for import

public class <%name%>DaoTest extends BasicDAOTest {
    
    
    /**
     * Test the insert of the entity <%name%>.<br/>
     * <ul><li>Step 1 : Create an entity</li>
     * <li>Step 2 : Verificar datos insert</li></ul>
     */
      public void testInsert() {        
        <%name%>Dao <%name.toLowerCase()%>Dao= new <%name%>Dao();
        DynaBean dynaBean = new LazyDynaBean();
        // <%startUserCode%> 
        <%for (attribute){%>
            <%if (type.name == "String"){%>
        dynaBean.set("<%name%>","<%i()+1%>");    
            <%}else if(type.name == "Date"){%>
        <%-- pValues.setDate(<%i()+1%>, new Date((String)dynaBean.get("<%name%>")); --%>    
            <%}else if(type.name == "Integer"){%>
        dynaBean.set("<%name%>",new Integer(<%i()+1%>));            
            <%}%>
        <%}%>
        // <%endUserCode%>
       
        <%name.toLowerCase()%>Dao.insert(dynaBean);
        String sqlQuery = "INSERT INTO <%tablaBDD%>";
        verifySQLStatementExecuted(sqlQuery+" (<%attribute.name.sep(", ")%>) VALUES (<%paramInserts.substring(0,paramInserts.length()-2)%>)");
        verifySQLStatementNotExecuted("UPDATE INTO <%tablaBDD%>a");
        int numDeParametr=1;
        <%for (attribute){%>
            <%if (type.name == "String"){%>
        verifySQLStatementParameter(sqlQuery, 0, numDeParametr, "<%i()+1%>");
        numDeParametr++; 
            <%}else if(type.name == "Date"){%>
        <%-- pValues.setDate(<%i()+1%>, new Date((String)dynaBean.get("<%name%>")); --%>
        <%-- numDeParametr++; --%> 
            <%}else if(type.name == "Integer"){%>
        verifySQLStatementParameter(sqlQuery, 0, numDeParametr, new Integer(<%i()+1%>));
        numDeParametr++;             
            <%}%>
        <%}%>
        verifyNotCommitted();        
        verifyAllResultSetsClosed();
        verifyAllStatementsClosed();
        //verifyConnectionClosed();
    }

    /**
     * Test the update of the entity <%name%>.<br/>
     * <ul><li>Step 1 : Create an entity</li>
     * <li>Step 2 : Verificar datos update</li></ul>
     */
    public final void testUpdate() {
       <%name%>Dao <%name.toLowerCase()%>Dao= new <%name%>Dao();
        DynaBean dynaBean = new LazyDynaBean();
        // <%startUserCode%>         
        <%for (attribute){%>                
            <%if (type.name == "String"){%>
        dynaBean.set("<%name%>","<%i()+1%>");    
            <%}else if(type.name == "Date"){%>
        <%-- pValues.setDate(<%i()+1%>, new Date((String)dynaBean.get("<%name%>")); --%>
            <%}else if(type.name == "Integer"){%>
        dynaBean.set("<%name%>",new Integer(<%i()+1%>));            
            <%}%>                    
        <%}%>
        // <%endUserCode%>
       
        <%name.toLowerCase()%>Dao.update(dynaBean);
        String sqlQuery = "UPDATE <%tablaBDD%> SET <%attribute.genComparator.sep(", ")%>";
        verifySQLStatementExecuted(sqlQuery);
        verifySQLStatementNotExecuted("UPDATE INTO <%tablaBDD%>a");
        int numDeParametr=1;
        <%for (attribute){%>
        <%if (isUnique){%>
            <%if (type.name == "String"){%>
        verifySQLStatementParameter(sqlQuery, 0, numDeParametr, String.valueOf(numDeParametr));
        numDeParametr++; 
            <%}else if(type.name == "Date"){%>
        <%-- pValues.setDate(<%i()+1%>, new Date((String)dynaBean.get("<%name%>")); --%>
        <%-- numDeParametr++; --%>
            <%}else if(type.name == "Integer"){%>
        verifySQLStatementParameter(sqlQuery, 0, numDeParametr, new Integer(numDeParametr));
        numDeParametr++;            
            <%}%>
        <%}%>
        <%}%>
        verifyNotCommitted();        
        verifyAllResultSetsClosed();
        verifyAllStatementsClosed();
        //verifyConnectionClosed();
    }
    
    /**
     * Test the update of the entity <%name%>.<br/>
     * <ul><li>Step 1 : Create an entity</li>
     * <li>Step 2 : Verificar datos update</li></ul>
     */
    public final void testDelete() {
       <%name%>Dao <%name.toLowerCase()%>Dao= new <%name%>Dao();
        DynaBean dynaBean = new LazyDynaBean();
        // <%startUserCode%>         
        <%for (attribute){%>    
            <%if (isUnique){%>            
                <%if (type.name == "String"){%>
        dynaBean.set("<%name%>","<%i()+1%>");    
                <%}else if(type.name == "Date"){%>
        <%-- pValues.setDate(<%i()+1%>, new Date((String)dynaBean.get("<%name%>")); --%>
                <%}else if(type.name == "Integer"){%>
        dynaBean.set("<%name%>",new Integer(<%i()+1%>));            
                <%}%>                    
            <%}%>
        <%}%>
        // <%endUserCode%>
       
        <%name.toLowerCase()%>Dao.delete(dynaBean);
        String sqlQuery = "DELETE FROM <%tablaBDD%> WHERE ";
        verifySQLStatementExecuted(sqlQuery);
        verifySQLStatementNotExecuted("UPDATE INTO <%tablaBDD%>a");
        // <%startUserCode%>         
        <%for (attribute){%>    
            <%if (isUnique){%>            
                <%if (type.name == "String"){%>
        verifySQLStatementParameter(sqlQuery, 0,<%i()+1%>,"<%i()+1%>");    
                <%}else if(type.name == "Date"){%>
        <%-- pValues.setDate(<%i()+1%>, new Date((String)dynaBean.get("<%name%>")); --%>
                <%}else if(type.name == "Integer"){%>
        verifySQLStatementParameter(sqlQuery, 0, <%i()+1%>,new Integer(<%i()+1%>));            
                <%}%>                    
            <%}%>
        <%}%>
        // <%endUserCode%>     
        verifyNotCommitted();        
        verifyAllResultSetsClosed();
        verifyAllStatementsClosed();
        //verifyConnectionClosed();
    }

    /**
     * Test the search by id para <%name%>.<br/>
     */
    public final void testFindById() {
        <%name%>Dao <%name.toLowerCase()%>Dao= new <%name%>Dao();
        DynaBean dynaBean = new LazyDynaBean();
        // <%startUserCode%>         
        <%for (attribute){%>    
            <%if (isUnique){%>            
                <%if (type.name == "String"){%>
        dynaBean.set("<%name%>","<%i()+1%>");    
                <%}else if(type.name == "Date"){%>
        <%-- pValues.setDate(<%i()+1%>, new Date((String)dynaBean.get("<%name%>")); --%>
                <%}else if(type.name == "Integer"){%>
        dynaBean.set("<%name%>",new Integer(<%i()+1%>));            
                <%}%>                    
            <%}%>
        <%}%>
        // <%endUserCode%>
       
        <%name.toLowerCase()%>Dao.findById(dynaBean);
        String sqlQuery = "SELECT <%attribute.name.sep(", ")%> FROM <%tablaBDD%> WHERE ";
        verifySQLStatementExecuted(sqlQuery);
        verifySQLStatementNotExecuted("UPDATE INTO <%tablaBDD%>");
        // <%startUserCode%>         
        <%for (attribute){%>    
            <%if (isUnique){%>            
                <%if (type.name == "String"){%>
        verifySQLStatementParameter(sqlQuery, 0,<%i()+1%>,"<%i()+1%>");    
                <%}else if(type.name == "Date"){%>
        <%-- pValues.setDate(<%i()+1%>, new Date((String)dynaBean.get("<%name%>")); --%>
                <%}else if(type.name == "Integer"){%>
        verifySQLStatementParameter(sqlQuery, 0, <%i()+1%>,new Integer(<%i()+1%>));            
                <%}%>                    
            <%}%>
        <%}%>
        // <%endUserCode%>     
        verifyNotCommitted();        
        verifyAllResultSetsClosed();
        verifyAllStatementsClosed();
        //verifyConnectionClosed();
    }

}


<%script type="Property" name="exempleValues"%>
<%if (type.name == "Integer"){%><%name.uniqueCode()%><%}else{%>
<%if (type.name == "String"){%>"my<%name.firstUpper()%>"<%}else{%>
<%if (type.name == "Boolean"){%>true<%}else{%>
<%if (type.name == "Date"){%>new Date(0)<%}else{%>
<%if (type.name == "Float"){%><%name.uniqueCode()%>.0<%}else{%>
new <%type.name%>()<%}%><%}%><%}%><%}%><%}%>

<%script type="Property" name="exempleValues2"%>
<%if (type.name == "Integer"){%><%name.uniqueCode()%><%}else{%>
<%if (type.name == "String"){%>"second<%name.firstUpper()%>"<%}else{%>
<%if (type.name == "Boolean"){%>false<%}else{%>
<%if (type.name == "Date"){%>new Date(1)<%}else{%>
<%if (type.name == "Float"){%><%name.uniqueCode()%>.0<%}else{%>
new <%type.name%>()<%}%><%}%><%}%><%}%><%}%>