Tuesday, December 7, 2010

Excluding xerces/xercesImpl from your CXF project

I'm not sure how much time I spent trying to figure out why my new service was not working, if I followed the same steps I usually follow on all my past CXF apps;
The only difference was to include a new dependency which has more business logic.

Then comparing my last CXF project lib folder with my new one, I found xercesImpl*.jar was additional to my current project.
I just removed from my POM (added as exclusion from my new dependency) and Listo! my CXF Web Service is working as expected :D

Thursday, December 2, 2010

Quest Toad on Oracle 11g not supported

Are you already on Oracle Database 11g?

Nevertheless, this post is to warn all developers out there using Quest TOAD for Oracle.
The current release of TOAD is 9.1, this version is not supported with Oracle 11g (client). But even more important, the version that comes out half of November, TOAD 9.5 (see screenshot below which is a beta), isn't working with the Oracle 11g client neither!
And looking around I found this message coming from Quest: Unfortunately, it was confirmed by our team's technical lead that Toad version 9.5 only support Oracle server 11g and not Oracle client 11g. My only suggestion for you is to install another client on your machine that is 10gR2 version or lower."

It's hard to believe that you need to install an Oracle Server just to get your development environment (TOAD) running ;-) Nevertheless, a workaround is to install Oracle 10g client, which I don't want to do as I'm connecting to 11g databases.
Or go for SQL Developer, a free alternative of Oracle.

A screenshot of the error "OCI version 11.1.0.1.0 is not supported"

Mendigos Oracle y TOAD!!!
I'm using both SQL Developer and TOAD as I think both have strengths and points to improve.
This post isn't to favor for SQL Developer, it's just to warn you.

Thursday, November 11, 2010

Conditions in One Line

Interesting point, how can I do 1 LINE If statements like in Java: This is the answer: I'll see on resultset cidb_order_id, 1 or 0 (segun sea el caso) The same sentence could be used on UPDATES:

Wednesday, October 27, 2010

My first official LEFT JOIN

When I was at school I always was afraid of using LEFT OR RIGHT Joins, well, almost 6 years after I'm done with school, I had to do my first one:

Tuesday, October 26, 2010

Add new parameter to Stored Procedure without impacting existing call

I have a Stored procedure already deployed in a production box, there is another porcess which wants to use it in a batch process, but the main batch process wants to control the transaction (commit/rollback). What can I do??
Add another parameter to my SP to handle the transaction or not, but If I do this the signature (DDL) of my SP is going to change!
There is one way to do this, something like adding polymorphism, on this case overload SP.
This is my original SP: On my iBatis side I'm calling this SP with this number of Params (5), If I add a new param, I'll have to add a new one to my DDL, right?
Not necessarily, because If you add another parameter but you don't declare it as IN neither OUT, it will be optional!!!
Then I can do this: And nobody will notice that I change it, because you can call it with 5 params (The 6th param will be given by default in the signature: DEFAULT 1) or with 6 (assigning 0 for example to the 6th parameter)
Inside the body of my SP I'm doing something like this:

Set Timeout when accessing Oracle with iBatis

Scenario:
There is a call which takes too much time, we don't want to wait until it's done, so in this case we can timeout our transaction and kill it on the Oracle side (well we don't kill/stop anything, we just abandon the process without any adverse impact);
Then we'll receive something like this from the DB:
ORA-01013: user requested cancel of current operation
How do you do that??
According to iBatis documentation, we can do it globally or for each statement/call we make by changing the value of defaultStatementTimeout
defaultStatementTimeout This setting is an integer value that will be applied as the JDBC query timeout for all statements. This value can be overridden with the “statement” attribute of any mapped statement. If not specified, no query timeout will be set unless specified on the “statement” attribute of a mapped statement. The specified value is the number of seconds the driver will wait for a statement to finish. Note that not all drivers support this setting.

Or we can do it Specifically for each statement element by setting the attribute timeout, for example:

Thursday, October 14, 2010

Create List of STRUCT based on a Query

This is my problem: I have a Stored Procedure which receives as parameter a List of Objects, this is my object

In Oracle to create a new instance of this kind of object, the default Contructor is given by definition of the object, for example in this case to create a new instance of CUST_ACCNT_MTN_PRE_ORDER, my contructor will be something like this
And this is my Collection/List/Table of Objects

My SP is something like this (As you'll see I'm using the same objects I defined in that entry)

And my solution is something like this
The secret is in this line: SELECT CUST_ACCNT_MTN_PRE_ORDER(CUST_ID, ACCT_NUM, NPA || NXX || TLN, -1, 'X', MTN_ORDER_TYPE, SYSDATE, NVL(EO_ALT_NPA||EO_ALT_NXX||EO_ALT_TLN,0)) BULK COLLECT INTO p_list
I'm creating for each row an object of type CUST_ACCNT_MTN_PRE_ORDER and then the ResultSet is set INTO p_list variable using BULK COLLECT, which fetch all rows once


IF you want to see my Stored Proc, this is what I did
CREATE OR REPLACE PROCEDURE record_ship_temp_orders(   
 out_orders_processed   OUT   NUMBER
)
IS
my_cust_id    CUST_ACCT_ORDER.cust_id%TYPE; 
my_acct_num    CUST_ACCT_ORDER.acct_num%TYPE;
my_pos_order_id    CUST_ACCT_ORDER.pos_order_id%TYPE;
my_pos_pre_order_id    CUST_ACCT_ORDER.pos_pre_order_id%TYPE;
my_pos_loc_cd    CUST_ACCT_ORDER.pos_loc_cd%TYPE;
my_total_order_lines    CUST_ACCT_ORDER.total_order_lines%TYPE;
my_ord_add_lines_cnt    CUST_ACCT_ORDER.add_lines_cnt%TYPE;   
my_ord_upg_lines_cnt    CUST_ACCT_ORDER.upg_lines_cnt%TYPE;  
p_list  CUST_ACCNT_MTN_PRE_ORDER_LIST; 
OUT_CIDB_ORDER_ID NUMBER;

--This is the main cursor 
CURSOR cur_test_init_load
    IS
    SELECT CUST_ID_NO AS CUST_ID, 
            ACCT_NO AS ACCT_NUM, 
            EQ_ORD_NO AS POS_ORDER_ID, 
            NULL AS POS_PRE_ORDER_ID, 
            NETACE_LOC_ID AS POS_LOC_CD             
    FROM TEST_INIT_LOAD
    GROUP BY CUST_ID_NO, ACCT_NO, EQ_ORD_NO, NULL, NETACE_LOC_ID
    ORDER BY CUST_ID_NO, ACCT_NO, EQ_ORD_NO, NETACE_LOC_ID;
    
/******************************************************************************
   NAME:    record_ship_temp_orders
   PURPOSE:    Retrieve data loaded into TEST_INIT_LOAD to be processed by
     Record_Pre_Order and then shipped by Ship_Pre_Order.
   DATE:    Oct 2010
   Referenced by:    To be executed internally

******************************************************************************/    
    
BEGIN 
DBMS_OUTPUT.put_line('Starting prcess '||TO_CHAR(SYSTIMESTAMP,'hh:mi:ss.FF'));
OPEN cur_test_init_load;  
        IF cur_test_init_load%NOTFOUND THEN         
  DBMS_OUTPUT.put_line('No data found on TEST_INIT_LOAD');   
  CLOSE cur_test_init_load;
  raise_application_error(-20102, 'No data found on TEST_INIT_LOAD');
 END IF; 
 
 out_orders_processed := cur_test_init_load%ROWCOUNT; --Before the first fetch, %ROWCOUNT returns 0
 
 DBMS_OUTPUT.put_line('Start record '||TO_CHAR(SYSTIMESTAMP,'hh:mi:ss.FF'));
 LOOP --Iterate cursor
 FETCH cur_test_init_load INTO my_cust_id, my_acct_num, my_pos_order_id, my_pos_pre_order_id, my_pos_loc_cd;
 
 IF out_orders_processed = 0 THEN
  out_orders_processed := cur_test_init_load%ROWCOUNT; --Set a value to the OUT param
 END IF;
 
 EXIT WHEN cur_test_init_load%NOTFOUND;--Exits when process is completed

 DBMS_OUTPUT.put_line('Processing  '||my_cust_id||'-'||my_acct_num||', my_pos_order_id='||my_pos_order_id||', my_pos_pre_order_id='||my_pos_pre_order_id||', my_pos_loc_cd='||my_pos_loc_cd);
 
  --Calculate total_order_lines, add_lines_cnt & upg_lines_cnt
            SELECT count(1) AS TOTAL_ODER_LINES INTO my_total_order_lines
            FROM TEST_INIT_LOAD
            WHERE CUST_ID_NO = my_cust_id
              AND ACCT_NO =  my_acct_num
              AND EQ_ORD_NO = my_pos_order_id;
              
            SELECT count(1) AS ADD_LINES_CNT INTO my_ord_add_lines_cnt
            FROM TEST_INIT_LOAD
            WHERE CUST_ID_NO = my_cust_id
              AND ACCT_NO =  my_acct_num
              AND EQ_ORD_NO = my_pos_order_id
              AND ESN_CHG_RSN_CD IS NULL;
  
            SELECT count(1) AS UPG_LINES_CNT INTO my_ord_upg_lines_cnt
            FROM TEST_INIT_LOAD
            WHERE CUST_ID_NO = my_cust_id
              AND ACCT_NO =  my_acct_num
              AND EQ_ORD_NO = my_pos_order_id
              AND ESN_CHG_RSN_CD IS NOT NULL;
              

 DBMS_OUTPUT.put_line('my_total_order_lines  '||my_total_order_lines||', my_ord_add_lines_cnt='||my_ord_add_lines_cnt||', my_ord_upg_lines_cnt='||my_ord_upg_lines_cnt);
              
               --Generate List of Items to be inserted into CUST_ACCT_MTN_ORDER
            SELECT CUST_ACCNT_MTN_PRE_ORDER(CUST_ID, ACCT_NUM, NPA || NXX || TLN, -1, 'X', MTN_ORDER_TYPE, SYSDATE, NVL(EO_ALT_NPA||EO_ALT_NXX||EO_ALT_TLN,0)) BULK COLLECT INTO p_list
            FROM (  
                SELECT CUST_ID_NO AS CUST_ID, 
                            ACCT_NO AS ACCT_NUM,
                            NPA , NXX , TLN,
                            NVL(ESN_CHG_RSN_CD,'A') AS MTN_ORDER_TYPE,
                            EO_ALT_NPA,EO_ALT_NXX,EO_ALT_TLN 
                FROM TEST_INIT_LOAD
                WHERE CUST_ID_NO = my_cust_id
                  AND ACCT_NO =  my_acct_num
                  AND EQ_ORD_NO = my_pos_order_id
                  AND ESN_CHG_RSN_CD IS NULL
  
                  UNION
  
                SELECT CUST_ID_NO AS CUST_ID, 
                            ACCT_NO AS ACCT_NUM,
                            NPA , NXX , TLN,
                            'U' AS MTN_ORDER_TYPE,
                            EO_ALT_NPA,EO_ALT_NXX,EO_ALT_TLN
                FROM TEST_INIT_LOAD
                WHERE CUST_ID_NO = my_cust_id
                  AND ACCT_NO =  my_acct_num
                  AND EQ_ORD_NO = my_pos_order_id 
                  AND ESN_CHG_RSN_CD IS NOT NULL    
            ); 
            
     FOR i in 1 .. p_list.count
     LOOP
  DBMS_OUTPUT.put_line ('STRUCT '||i||'=> mtn='||p_list(i).mtn||', mtn_order_type='||p_list(i).mtn_order_type||', bdy_mtn='||p_list(i).bdy_mtn);
     END LOOP;  
     --Call SP's
      BEGIN 
   DBMS_OUTPUT.put_line('Calling Record_Pre_Order');
   RECORD_PRE_ORDER ( my_cust_id, my_acct_num, my_pos_order_id, my_pos_pre_order_id, my_pos_loc_cd, my_total_order_lines, my_ord_add_lines_cnt, my_ord_upg_lines_cnt, 0, p_list, OUT_CIDB_ORDER_ID );
   DBMS_OUTPUT.put_line('Calling Ship_Pre_Order');
   SHIP_PRE_ORDER ( my_cust_id, my_acct_num, my_pos_order_id, my_pos_loc_cd, OUT_CIDB_ORDER_ID ); 
   DBMS_OUTPUT.put_line('End record '||TO_CHAR(SYSTIMESTAMP,'hh:mi:ss.FF'));
   DBMS_OUTPUT.put_line('-------');
   p_list := NULL;
  EXCEPTION
      WHEN OTHERS
      THEN
      DBMS_OUTPUT.put_line ('***ERROR*** '||SQLERRM);
      out_orders_processed := out_orders_processed - 1; --Decrease failed orders
  END;
 END LOOP; 
DBMS_OUTPUT.put_line('Process completed');
DBMS_OUTPUT.put_line('End of process '||TO_CHAR(SYSTIMESTAMP,'hh:mi:ss.FF'));
CLOSE cur_test_init_load;
 
EXCEPTION
   WHEN OTHERS
   THEN
      DBMS_OUTPUT.put_line (SQLERRM);
      ROLLBACK;
      RAISE;
END;
/

Friday, October 8, 2010

SQL Joins explained with Venn's Diagrams

SQL Joins explicados de forma grƔfica con diagramas Venn

Una simple ayuda

El lenguaje SQL es aveces el gran olvidado por los desarrolladores, cada vez abundan mas los frameworks que abstraen al desarrollador del contacto con el modelo de negocio.

He escrito este documento, basƔndome en otros similares para ayudar a entender con un diagrama de Vann, los diferentes tipos de Join's que SQL92 soporta.

Existen tecnologĆ­as que abstraen completamente del modelo de negocio, para el desarrollador funcionan creando una serie de clases de Dominio que define el modelo, sin importar quĆ© base de datos o de quĆ© fabricante sea esta. Por ejemplo Ruby on Rails, GRails, ... usando un conjunto de tecnologĆ­as, como Hibernate configuradas por convenciĆ³n dentro del propio framework.

TambiƩn es muy extendido el uso de aplicaciones que permiten modelar el negocio de forma grƔfica, ERM (como DBSchema), y normalmente despuƩs se usa un ORM's que les hacen el trabajo sucio de forma elegante y segura.

Todo vale, pero la realidad de las empresas TIC es que necesitan profesionales serios y conscientes que entiendan y controlen todas las capas para que un sistema funciona como se espera y estƔ diseƱado, y no se deje nada al azar.

El desarrollador, muy frecuentemente recurre a activar trazas o aplicaciones de monitorizaciĆ³n de actividad que nos desvelen, quĆ© estĆ” haciendo nuestro framework con nuestro modelo de negocio. Existen aplicaciones que esnifan directamente de la base de datos esta informaciĆ³n para que podamos analizarla, el obsoleto Profile y Analyzer que incluĆ­a Microsoft SQL Server es un ejemplo de ellos.

Finalmente cuando tenemos delante la query sucede que hace tanto tiempo que no trabajamos con SQL que no entendemos quƩ hace exactamente, sobre todo si estƔ trabajando con tablas relacionadas y nos encontramos con una consulta que afecta a varias entidades.

Espero que este documento ayude a reducir el tiempo invertido a descubrir porquƩ se comporta una SQL de un modo u otro.


Convenciones

Este documento asume que siempre que la "TABLA A" esta a la izquierda y la "TABLA B" a la derecha de las sentencias.

Para los ejemplos vamos a utilizar 2 tablas que van a contener los siguientes datos:

id name | id name
1 Roberto | 1 Alex
2 Juan | 2 Carlos
3 RubƩn | 3 Juan
4 Carlos | 4 SaĆŗl



INNER JOIN

SELECT * FROM TableA INNER JOIN TableB ON TableA.name = TableB.name

id name | id name
2 Juan | 2 Carlos
4 Carlos | 3 Juan

El resultado son solo el conjunto de registros que coinciden en ambas tablas.


Inner Join

FULL OUTER JOIN

SELECT * FROM TableA FULL OUTER JOIN TableB ON TableA.name = TableB.name

id name | id name
1 Roberto | null null
2 Juan | 3 Juan
3 RubƩn | null null
4 Carlos | 2 Carlos
null null | 1 Alex
null null | 4 SaĆŗl

El resultado es el conjunto total de registros de ambas tablas, coincidiendo aquellos registros cuando sea posible. Si no hay conicidencias, se asignan nulos.


Full Outer Join

FULL OUTER JOIN WHERE

SELECT * FROM TableA FULL OUTER JOIN TableB ON TableA.name = TableB.name WHERE TableA.id IS null OR TableB.id IS null

id name | id name
1 Roberto | null null
3 RubƩn | null null
null null | 1 Alex
null null | 4 SaĆŗl

El resultado es un conjunto de records Ćŗnicos en la TablaA y en la TablaB, hacemos el Full Outer Join y excluimos los registros que no queremos con el Where


Full Outer Join con Where

LEFT OUTER JOIN

SELECT * FROM TableA LEFT OUTER JOIN TableB ON TableA.name = TableB.name

id name | id name
1 Roberto | null null
2 Juan | 3 Juan
3 RubƩn | null null
4 Carlos | 2 Carlos

El resultado son todos los registros de la TablaA, y si es posible las coincidencias de la TablaB. Si no hay coincidencias, el lado derecho mostrarĆ” nulos.


Left Outer Join

LEFT OUTER JOIN WHERE

SELECT * FROM TableA LEFT OUTER JOIN TableB ON TableA.name = TableB.name WHERE TableB.id IS null

id name | id name
1 Roberto | null null
3 RubƩn | null null

El resultado es un conjunto de registros que solo estƔn en la TablaA, no en la TablaB. Hacemos lo mismo que en un Left Outer Join, pero eliminamos los registros que no queremos de la TablaB con el Where


Left Outer Join con Where

CROSS JOIN

Existe tambiƩn la posibilidad de cruzar todos los registros con todos (producto cartesiano), imposible de dibujar con un diagramas Venn

SELECT * FROM TableA CROSS JOIN TableB

Imaginarse el resultado de todos los registros por todos es muy fƔcil, si tenemos 4 registros en cada tabla 4 x 4 = 16.
Cross Join
¡Ojo al hacer esto en tablas con muchos registros!

Thursday, September 30, 2010

Validation Query on WebSphere DataSource

Do you remember this?? (for those who have worked before with DBCP : validationQuery)

I was tired to look for this attribute in Websphere and I found it :P


Tip: On DB2 the equivalent to SELECT 1 FROM DUAL is SELECT 1 FROM SYSIBM.SYSDUMMY1

Monday, September 20, 2010

Pass Collection of Objects with Attributes to a Stored Procedure using iBatis

In my last entry I had a requirement which needed to pass a List to an Oracle Stored Procedure, well, that thing is history.
But now the problem becomes more complex, because, what happen if I'm expecting on my Stored Proc and Type (STRUCT)
This is my Collection in Oracle!
And this is my Stored Proc (this is just a sample which receives the TABLE of Records)
This is the table where I'm going to INSERT
Obviously, the solution is Create a Handler like I did on my last entry, but is not going to be as simple, because I need to Map my Oracle STRUCT with my Java Code, so I have to do an domain object (POJO) coupled to Oracle and my Handler.
Once we have our Mapper class, then let's do the Handler!!!
And this is how it looks my Map (XML)

In case you have to receive the Array from your Stored Proc, you just have to write in your Handler somethig like this:

References: Using iBatis with a stored function returning a Collection Type and Oracle UDT Collections as IN and OUT parameters with iBatis

Friday, September 17, 2010

Pass Collection to Stored Procedure using iBatis

Today I had a really crazy idea: "Why not making my query work with a list of parameters like I do with Hibernate using the operator IN???"
It sounds simple, Isn't it??? Ok, then try to do it with an Stored Procedure in Oracle :P
Then, this is my Stored Proc (I had to create a Type to have support for Arrays in Oracle, because an Array is not a simple-provided data type): As you can see, my dear visitor, I'm expecting some simple parameters and I'm returning a ResultSet, really straight forward, but the problem comes with the Array of NUMBER (that's why I created my
TYPE NUMBER_ARRAY AS TABLE OF NUMBER
)

The solution to this problem is easier than it seems, just create a Handler dude!!! The magic begins when I transform the Connection (because I have to work at the connection level) provided by the Application Server (WebSphere on this case - If this happens to me on another App Server or with another Connection Pool, I'm going to be in trouble, because the issue will be how to retrieve a Native java.sql.Connection, but that will be another story).
Let's analyze this monster:
* Get Native Connection
*Create my ArrayDescriptor for my Type (these NUMBER_ARRAY is my TYPE I created previously)
*Create my parameter, an ARRAY (al fin y al cabo) and we're set!

Finally this is my mapping file for my stored procedure

And my code lived happily ever after!!! Abur!!!

Friday, September 10, 2010

JDBC url for oracle RAC

If you have to connect to oracle RAC (Real Application Cluster) using JDBC with thin driver, the classic url:
jdbc:oracle:thin:@<HOST>:1521:<SID>
doesn’t work and you get the error ORA – 12505.
Instead, you must use this url:
jdbc:oracle:thin:@(DESCRIPTION=(LOAD_BALANCE=on)
(ADDRESS=(PROTOCOL=TCP)(HOST=host1) (PORT=1521))
(ADDRESS=(PROTOCOL=TCP)(HOST=host2) (PORT=1521))
(CONNECT_DATA=(SERVICE_NAME=service)))
If you have an oracle client, like toad, check the tsnames.ora for the correct values of SERVICE_NAME and host.

Wednesday, September 8, 2010

Log SQL Statements on Hibernate

Hibernate, in the end, is all about dispatching SQL statements. SQL is at the heart of communication with an RDBMS system, and it is extremely important when struggling through performance problems or other bugs, that you know what is going on. After all, knowing the executed SQL allows you to determine the number of queries to complete an O/R mapping task, not to mention that seeing SQL queries is critical to understanding how to optimize the queries via indices and other database settings.
There are two ways (due to the legacy of Hibernate) to enable SQL logging. The first is to simply enable SQL logging in the Hibernate configuration By setting the hibernate.show_sql to TRUE

This is a nice quick and dirty solution, but it is relatively inflexible. SQL statements are always logged to System.out when that property is enabled, and on some servers, System.out isn't accessible by the average developer; or is cluttered with a million other log statements.

Alternatively, Hibernate uses the Apache-Jakarta Commons Logging package, which means that it will utilize log4j , java.util.logging , or potentially another logging framework. Typically, log messages are sent to commons logging, and then they are dispatched to one of these logging frameworks. Then, those logging frameworks determine where the message should be sent (log files, sockets, emails, database records, system out, system err, etc). It is easy to see how using these log frameworks will increase the flexibility of log statements. With Hibernate, simply setting the org.hibernate.SQL logger to 'DEBUG' or 'ALL' will ensure that all SQL statements are logged to the console.


If you set up a log4j category for org.hibernate.type
Get it to write out to the same log file as the org.hibernate.SQL
The type one will list the parameters for you after the SQL e.g.
2006-07-28 09:57:12,061 DEBUG org.hibernate.SQL - insert into BASKET_LINE_ALLOC (LAST_UPDATED, QUANTITY, CUSTOMER_REF, NOTES, BRANCH_ID, FUND_ID, TEMPLATE_ID, 
BASKET_LINE_ALLOC_ID) values (?, ?, ?, ?, ?, ?, ?, ?) 
2006-07-28 09:57:12,081 DEBUG org.hibernate.type.TimestampType - binding '2006-07-28 09:57:12' to parameter: 1 
2006-07-28 09:57:12,081 DEBUG org.hibernate.type.IntegerType - binding '3' to parameter: 2 
2006-07-28 09:57:12,082 DEBUG org.hibernate.type.StringType - binding '' to parameter: 3 
2006-07-28 09:57:12,082 DEBUG org.hibernate.type.StringType - binding '' to parameter: 4 
2006-07-28 09:57:12,082 DEBUG org.hibernate.type.LongType - binding '511' to parameter: 5 
2006-07-28 09:57:12,082 DEBUG org.hibernate.type.LongType - binding '512' to parameter: 6 
2006-07-28 09:57:12,082 DEBUG org.hibernate.type.LongType - binding null to parameter: 7 
2006-07-28 09:57:12,082 DEBUG org.hibernate.type.LongType - binding '180030' to parameter: 8 

@Autowired and @Qualifier

"Your best friends could be @Autowired and @Qualifier"
I have to migrate data from DB2 to Oracle, both databases have the same structure, well, my Oracle has better design, but I'm reusing the some objects, like POJO's and DAO's, the only thing I changed were my mappings, because I have to keep my mappings for DB2 and for Oracle.
If I have the same DAO for both databases, what can I do?
daoApplicationContext.xml
As you can see, I have 2 different DAO's sharing the same Interface & Implementation, but each one belongs to a different "sessionFactory" serviceApplicationContext.xml
Nothing special, right? But now here it comes the interesting part, because @Autowired by itself it will inject the given bean in your ServiceImpl, but you must have only one bean of that type. In my case I have more than 1, so @Autowired will throw an error when loading the context.
Then it comes @Qualifier which will match based on the given name, and problem solved chavos!!!

Notes: I used org.springframework.beans.BeanUtils to create a copy of my bean (pojo) returned from DB2 into a non-persistent Pojo which I'll manipulate before inserting into Oracle (DB2 completes each column value with spaces to achieve the given size of that column, so each time you query a DB2 column you'll get a lot of extra spaces)

Wednesday, September 1, 2010

EmbeddedId in Hibernate, AnnotatedClasses

I had to do some inserts to a table with a composite PK:



Nothing special, I decided to use Hibernate with annotations (but what about the PK: just create another class -duh, but How can I tell hibernate this is my PK? @EmbeddedId and @Embeddable):
@Embeddable
Defines my composite PK
@EmbeddedId
Includes my composite Pk in my main Pojo
If you want to include in your sessionFactory (daoApplicationContext.xml) my annotated pojos, add this entry
As a reminder, if you want to use a propeties file to provide parameter for your DataSource, you have to do this:

Thursday, August 19, 2010

How to test servlet using Telnet

Essentially what I need to do is just make an HTTP Call using Telnet.

$> telnet 127.0.0.1 9086
Ok, I'm connected, and now what??
I know which servlet I want to test, I know which parameters is expecting, then "let's do it":

Which method should I use? POST or GET?? let's use POST (due to well known limitations with GET)

This is my URL:
/MyWebApp/proxyServlet?operation=doSomethingNice&consumerName=myActiveMQConsumers&server=192.168.5.122:9080&targetServlet=/MyOtherWebApp/utilsServlet
I'll finish my command with the HTTP version I want to use: HTTP/1.0 (if I use 1.1 it'll keep you connected)

And finally let's put all together:

Important: Once you have copied this full line in your telnet body, please type ENTER twice.

How do I know if this works? You should see this on your telnet console:
HTTP/1.0 200 OK
Content-Type: text/xml;charset=ISO-8859-1
Cache-Control: no-cache
Content-Language: en-US
Content-Length: 21
Date: Thu, 19 Aug 2010 18:38:45 GMT
Server: WebSphere Application Server/6.1

true

Connection to host lost.

Tuesday, August 17, 2010

Small Proxy App based on Apache Mina 2.0.0-RC1

What I'm going to do is develop a small app which basically is going to broadcast a message received to another host in a defined port.
My small app is just a standalone app based on Apache Mina, is going to be listening on "X" port and it's going to broadcast message received to another app which is a blackbox. So simple, Isn't it?


What do you need?
  • mina-filter-compression-2.0.0-RC1.jar
  • mina-integration-xbean-2.0.0-RC1.jar
  • slf4j-log4j12-1.5.0.jar
  • mina-integration-beans-2.0.0-RC1.jar
  • jzlib-1.0.7.jar
  • jaxen-1.1.1.jar
  • mina-transport-apr-2.0.0-RC1.jar
  • log4j-1.2.15.jar
  • slf4j-api-1.5.0.jar
  • mina-core-2.0.0-RC1.jar
Or simple, you can get the full distribution and get them all in one single file.
This jar is just a luxury, but it's necesary, because I don't want to reinvent the wheel: commons-lang-2.3.jar

Well, time to work, the first thing you should code is the main class, my ProxyServer and 2 IoHandlers (ProxyHandlerAdapter & ClientHandlerAdapter).


And this is my code







How can I test it??? Just by create a client using java.net.Socket or just by using Telnet to that particular port

I didn't include other classes because they're not important

Log4J tips

Add thread name to my log file; sometimes we want to know which thread is being executed, well, try this:
ConversionPattern=%d [%5p] [%t] %c{1}.%m%n

That's right just by adding "%t", you can see which thread is doing what.


Friday, August 13, 2010

Spring MVC - Binding VO to a Form

Problema:
I have a VO and I wanted to populate it on my JSP and on my controller just process the VO already populated.

Solution:

On my POST method I'll handle my VO already populated.
This entry will do 50% of the job @ModelAttribute(value="LoggerVO") LoggerVO loggerVO
On my JSP I'll map using spring's tag library
By doing this modelAttribute="LoggerVO" commandName="LoggerVO"
I'm matching what I have on my form and what I have on my Controller
I hope this will help you!
Salu2

Wednesday, August 11, 2010

Cross Domain issue - Ajax

Who say yes???
I was working in a GUI for controlling components in different servers from one server - stopping, starting, purging queues & consumers; finally beans
The firSt thing it came to my mind was: "let's do it with AJAX to avoid multiple calls and decrease the traffic!!!"
Which AJAX framework should I choose??? Let's learn jQuery, because that one has a bunch of cool features which will be really helpfull to develop my GUI (check this site: flowplayer.org they have a bunch of demos which are really easy to follow and all based on jQuery)
My first issue was learnign that Ajax call, but after a few hours I could do my first ajax call using jQuery (I have a servlet which returns XML or JSON)

Now what??? If I'm accessing the servlet in the same context - domain, everything works fine, but... If I try to access my servlet but in another server

Tons tuve que eccharle coco
My solution was to create a ProxyServlet which basically will take my request and pass it to the remote server & servlet using an HttpClient and in the same way, it will get the response coming from the remote servlet, in other words, my ProxyServlet (in the same domain - context) will be the only one talking to my Ajax call, eventhough ProxyServlet will be talking to the remote server & servlet. Then I did it again  

This is my code:

This is my main servlet (the one which returns XML or JSON using json-simple project)

And this now, these are portions of my jQuery code:


You can get the additional JavaScript libraries from: JSON2 and my version of jQuery Tools