Wednesday

Deploy apache archiva 1.3.3 on Oracle Weblogic server

Deploy Apache Archiva web application archive (war) is not straight forward on WebLogic, although on apache site it declared that, it should be deploy on any J2ee server. This week we decided to upgrade our Archiva version from 1.3 to 1.3.3 and locate some interesting facts which should be fix to deploy on WebLogic server. In this following blog post you can get some useful information to deploy version 1.3 on WebLogic server. In this current post i am going to explain the maven way to fix all the problems among with Jpox ORM (we have oracle DB 10.3.1 as external database) and mailSession of Archiva to deploy on WebLogic. Most of all configuration you will get from the Apache Archiva site.
At first we have to download the source code of the Apache Archiva. You could found it here.Unzip the archive file and run mvn clean install -Dmaven.test.skip=true, it will download a few more plugin and dependency libraries to compile and install the artifact on you local machine (Assume that you already have mvn installed on your system).
Our aim is to add one weblogic.xml descriptor file to archiva-webapp/src/main/webapp/WEB-INF, add one maven ear module on archiva-web module to get ear artifact and edit archiva-base.xml file to change the column length.
First of all we will add following weblogic.xml in the \src\apache-archiva-1.3.3-src\archiva-modules\archiva-web\archiva-webapp\src\main\webapp\WEB-INF directory.
<?xml version = '1.0' encoding = 'windows-1252'?>
<weblogic-web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xsi:schemaLocation="http://www.bea.com/ns/weblogic/weblogic-web-app http://www.bea.com/ns/weblogic/weblogic-web-app/1.0/weblogic-web-app.xsd"
                  xmlns="http://www.bea.com/ns/weblogic/weblogic-web-app">
  <resource-description>
    <res-ref-name>mail/Session
    <jndi-name>mail/Session
  </resource-description>
</weblogic-web-app> 
Which will active resource location by jndi
Next we have to make some change on archive-base.xml located on \src\apache-archiva-1.3.3-src\archiva-modules\archiva-base\archiva-model\src\main\mdo . By default Archiva released with Jpox orm which data base object mapping is not supported for Oracle data types. Change the mapping for column named "message" for table  REPOSITORY_PROBLEMS as follows:
 <field stash.maxSize="4000">
  <name>message</name>
  <identifier>false</identifier>
  <version>1.0.0+</version>
  <required>true</required>
  <type>String</type>
  <description>
    The origin of the health problem.
  </description>
</field> 
Change the length of the field named "message" for table LICENSES as follows:
 <field stash.maxSize="4000">
  <name>comments</name>
  <version>1.0.0+</version>
  <type>String</type>
  <description>
    Addendum information pertaining to this license.
  </description>
</field> 
Edit the length of the field named "description"for tables PROJECT as follows:
 <field stash.maxSize="4000">
  <name>description</name>
  <identifier>false</identifier>
  <version>1.0.0+</version>
  <required>false</required>
  <type>String</type>
  <description>
    The description of this project.
  </description>
</field> 

Thursday

JRebel version 3.5 released

I6 November released JRebel version 3.5. JRebel is an award winning productivity tool for Java EE development. JRebel maps your project workspace directly to your running application. When a developer makes a change to any class or resource in their IDE the change is immediately reflected in the application, skipping the build and redeploy phases. See the leaflet here
It takes only a few simple steps to configure and works out.
1) Download the installer from the following location
http://www.zeroturnaround.com/jrebel/current
2) Run the setup file
3) Add JRebel plugin in the projects root maven pom.xml as follows:
<plugin>
  <groupId>org.zeroturnaround</groupId>
  <artifactId>jrebel-maven-plugin</artifactId>
  <executions>
    <execution>
      <id>generate-rebel-xml</id>
      <phase>process-resources</phase>
      <goals>
        <goal>generate</goal>
      </goals>
    </execution>
  </executions>
</plugin>
This will generate JRebel configuration file rebel.xml automatically on every build. If you want to generate the rebel.xml manually run mvn jrebel:generate -Drebel.xml.dir=OUTPUT_DIRECTORY

Friday

Manipulation Oracle Bpm directory with FDI api

The BPM Directory is an information repository. It stores configuration information about a BPM Environment. This repository is a fundamental component of the BPM Environment; a BPM Environment cannot exist without a BPM Directory. All the users information and organizational unit information maintains on BPM directory. Oracle BPM also provides API named FDI to CRUD operations on these information. For more additional information see here. In this current post, i will provide sample java code which will help to quick start with FDI.
Fdi Api is not public api to use, for these reason only a few reference found on the web. Oracle BPM Standard Components Reference provides most of the information to working with FDI. For example purpose, i will use Bpm Standalone Enterprise server directory.xml. To run standalone client we have to need following libraries on class path:
  • fuegopapi-client.jar
  • b1oracle.jar
  • b1base.jar
  • b1util.jar
  • b1resource.jar

Here is my maven pom.xml file
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>ru.fors.nsi.bpm.proxy</groupId>
<artifactId>bpmproxy</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>bpmproxy</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>fuego</groupId>
<artifactId>fuegopapi-client</artifactId>
<version>6.5.0</version>
<!--<scope>provided</scope>-->  
</dependency>
<dependency>
<groupId>javax.ejb</groupId>
<artifactId>ejb</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>albpm.jdbc.oracle</groupId>
<artifactId>b1oracle</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>albpm.jdbc.base</groupId>
<artifactId>b1base</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>albpm.util</groupId>
<artifactId>b1util</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
<version>1.1</version>
</dependency>
<!--<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</dependency>-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>1.6.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<testFailureIgnore>true</testFailureIgnore>
<skip>true</skip>
</configuration>
</plugin>          
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>      
</build>
</project>

Here is my directory.xml, which must be on classpath.
<?xml version="1.0" encoding="UTF-8"?>
<?fuego version="6.5.1" build="94375"?>
<DirectoryConfiguration>
<id>default</id>
<description>Default Directory Configuration</description>
<admin>admin</admin>
<adminPass><encrypted>uPgrjqI482A=</adminPass>
<presets>
<preset name="engine">
<property name="participant" value="admin"/>
<property name="participant_password" value="<encrypted>uPgrjqI482A="/>
</preset>
<preset name="xobjects">
<property name="participant" value="admin"/>
<property name="participant_password" value="<encrypted>uPgrjqI482A="/>
</preset>
<preset name="portal-anonymous">
<property name="participant" value="admin"/>
<property name="participant_password" value="<encrypted>uPgrjqI482A="/>
</preset>
<preset name="datawarehouse">
<property name="participant" value="admin"/>
<property name="participant_password" value="<encrypted>uPgrjqI482A="/>
</preset>
<preset name="papiws-anonymous">
<property name="participant" value="admin"/>
<property name="participant_password" value="<encrypted>uPgrjqI482A="/>
</preset>
</presets>
<set>
<configuration name="fuego" type="SQL" subtype="DDORACLE">
<property name="jdbc.pool.idle_timeout" value="5"/>
<property name="jdbc.pool.entry.max" value="10"/>
<property name="oracle.dateEqualsTimestamp" value="false"/>
<property name="jdbc.host" value="xyz"/>
<property name="user" value="OBPMDirLocal"/>
<property name="jdbc.port" value="1521"/>
<property name="jdbc.pool.min" value="0"/>
<property name="jdbc.pool.maxopencursors" value="100"/>
<property name="oracle.sid" value="ftsdb"/>
<property name="password" value="<encrypted>ko8PrHu2UJLLicio"/>
<property name="jdbc.xa" value="false"/>
<property name="jdbc.pool.max" value="10"/>
</configuration>
</set>
</DirectoryConfiguration>

Thursday

Resolve NullPointerException at weblogic.wsee.jaxws.spi.ClientIdentityRegistry.internalAddClientRuntimeMBean

One of our project running on Solaris Sparc system on production, last week we have deployed newer version of our project which have to integrate with 3rd party webservices. On development platform all the test goes fine on Weblogic 10.3.3, but on production we got the following Nullpointer exception:
05-10-2010 18:48:01.066 ERROR r.f.t.a.service.AuctionAOPLogger - Exception:

java.lang.NullPointerException: null

at weblogic.wsee.jaxws.spi.ClientIdentityRegistry.internalAddClientRuntimeMBean(ClientIdentityRegistry.java:470) ~[weblogic.jar:10.3.3.0]

at weblogic.wsee.jaxws.spi.ClientIdentityRegistry.addClientRuntimeMBean(ClientIdentityRegistry.java:424) ~[weblogic.jar:10.3.3.0]

at weblogic.wsee.jaxws.tubeline.standard.WseeClientTube.register(WseeClientTube.java:54) ~[weblogic.jar:10.3.3.0]

at weblogic.wsee.jaxws.tubeline.standard.WseeClientTube.(WseeClientTube.java:35) ~[weblogic.jar:10.3.3.0]

at weblogic.wsee.jaxws.tubeline.standard.StandardTubelineDeploymentListener$1.createClient(StandardTubelineDeploymentListener.java:52) ~[weblogic.jar:10.3.3.0]

at weblogic.wsee.jaxws.WLSTubelineAssemblerFactory$TubelineAssemblerImpl.createClient(WLSTubelineAssemblerFactory.java:148) ~[weblogic.jar:10.3.3.0]

at com.sun.xml.ws.client.WSServiceDelegate.createPipeline(WSServiceDelegate.java:467) ~[glassfish.jaxws.rt_1.0.0.0_2-1-5.jar:2.1.5]

at com.sun.xml.ws.client.WSServiceDelegate.getStubHandler(WSServiceDelegate.java:689) ~[glassfish.jaxws.rt_1.0.0.0_2-1-5.jar:2.1.5]

at com.sun.xml.ws.client.WSServiceDelegate.createEndpointIFBaseProxy(WSServiceDelegate.java:667) ~[glassfish.jaxws.rt_1.0.0.0_2-1-5.jar:2.1.5]

at com.sun.xml.ws.client.WSServiceDelegate.getPort(WSServiceDelegate.java:362) ~[glassfish.jaxws.rt_1.0.0.0_2-1-5.jar:2.1.5]

at com.sun.xml.ws.client.WSServiceDelegate.getPort(WSServiceDelegate.java:344) ~[glassfish.jaxws.rt_1.0.0.0_2-1-5.jar:2.1.5]

at com.sun.xml.ws.client.WSServiceDelegate.getPort(WSServiceDelegate.java:326) ~[glassfish.jaxws.rt_1.0.0.0_2-1-5.jar:2.1.5]

at javax.xml.ws.Service.getPort(Service.java:92) ~[na:1.6.0_20]

at ru.fors.trade.rosim.ws.client.CheckAuctionServices.getBasicHttpBindingICheckAuctionServices(CheckAuctionServices.java:56) ~[rosim-confirmation-2.0.6.2.jar:na]

at ru.fors.trade.auction.service.RosimServiceImpl.checkAuctionCorrect(RosimServiceImpl.java:47) ~[auction-common-2.0.6.2.jar:na]

at sun.reflect.GeneratedMethodAccessor683.invoke(Unknown Source) ~[na:na]

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) ~[na:1.6.0_20]

at java.lang.reflect.Method.invoke(Method.java:597) ~[na:1.6.0_20]

at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307) [spring-aop-2.5.6.jar:2.5.6]

at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182) ~[spring-aop-2.5.6.jar:2.5.6]

at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149) ~[spring-aop-2.5.6.jar:2.5.6]

at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:54) [spring-aop-2.5.6.jar:2.5.6]

at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) ~[spring-aop-2.5.6.jar:2.5.6]

at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89) ~[spring-aop-2.5.6.jar:2.5.6]

at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) ~[spring-aop-2.5.6.jar:2.5.6]

at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204) [spring-aop-2.5.6.jar:2.5.6]

at $Proxy139.checkAuctionCorrect(Unknown Source) [na:na]

at ru.fors.trade.auction.service.AuctionServiceImpl.checkForRosimSendOrUpdate(AuctionServiceImpl.java:1457) [auction-common-2.0.6.2.jar:na]

at sun.reflect.GeneratedMethodAccessor682.invoke(Unknown Source) ~[na:na]

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) ~[na:1.6.0_20]

at java.lang.reflect.Method.invoke(Method.java:597) ~[na:1.6.0_20]

at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307) [spring-aop-2.5.6.jar:2.5.6]

at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182) ~[spring-aop-2.5.6.jar:2.5.6]

at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149) ~[spring-aop-2.5.6.jar:2.5.6]

at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:54) [spring-aop-2.5.6.jar:2.5.6]

at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) ~[spring-aop-2.5.6.jar:2.5.6]

at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106) [spring-tx-2.5.6.jar:2.5.6]

at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) ~[spring-aop-2.5.6.jar:2.5.6]

at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89) ~[spring-aop-2.5.6.jar:2.5.6]

at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) ~[spring-aop-2.5.6.jar:2.5.6]

at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204) [spring-aop-2.5.6.jar:2.5.6]
At first glance it seems, client trying to add client identification on request.
After some googling on web i have just found one forum thread with no answer.


Monday

Oracle service bus logging with custom JDBCAppander

Last few weeks we are upgrading logging system of our MDM system, we have design a central place for all logging data. With central log system we can afford to manage our system very effectively and debug any fatal error. With OSB it's not straight forword to pulling logging data from console to somewhere, because a few subsystem uses different appender to write and filter log. See the following link to know more about oracle logging service. In my previous post i demonstrate how to use log4j JDBC appender in log4j.properties to redirect log to database table.
For the current post we also uses same DDL to create tables
1)
CREATE TABLE LOGS 
(USER_ID VARCHAR2(20), 
DOMAIN  varchar2(50), 
DATED   DATE NOT NULL, 
LOGGER  VARCHAR2(500) NOT NULL, 
LEVEL   VARCHAR2(50) NOT NULL, 
MESSAGE VARCHAR2(4000) NOT NULL 
);

2) Create a simple maven project with a few dependency to create custom JDBCAppender
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>ru.xyz.wl.logging</groupId>
<artifactId>jdbc-logging</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>

<name>jdbc-logging</name>
<url>http://maven.apache.org</url>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>weblogic</groupId>
<artifactId>wlfullclient</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>weblogic</groupId>
<artifactId>wllog4j</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
<encoding>UTF-8</encoding>
</configuration>               
</plugin>
</plugins>
</build>
</project>

assume that you have already installed wlfullclient.jar and wllog4j.jar in your maven local repository.
3) Now it's time for coding, create two java class as follows:
package ru.xyz.wl.logging;

import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.spi.LoggingEvent;

import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import java.sql.*;

import weblogic.logging.log4j.WLLog4jLogEvent;

/**

*/
public class JDBCAppender extends AppenderSkeleton {
private Connection conn;
private PreparedStatement stm;
private String subSysName;
public JDBCAppender(String subSysName) {
this.subSysName = subSysName;
// get Initial ctx
try {
InitialContext ctx = new InitialContext();
DataSource dataSource = (DataSource) ctx.lookup("jdbc/logDataSource");
conn = dataSource.getConnection();
stm = conn.prepareStatement("INSERT INTO EXT_LOGS2 VALUES(?,?,?,?,?,?)");
stm.setEscapeProcessing(true);
conn.setAutoCommit(true);

} catch (NamingException e) {
e.printStackTrace();
} catch(SQLException e){
e.printStackTrace();
}

}

Sunday

A quick fix to set Locale on OOO (Open office org)

One of our web application uses OOO(open office org 3.2) to convert msOffice file to HTML file. There are a open source project named JodConverter which helps you to do most of the low level works such as connecting to server and much more. For quick start you can see my previous post. Few days ago we got a bug about Russian encoding after converting big Ms Word file to Html, as a usual our developers done their all the best to get rid of it, put directives on html and much more, but all in vain. Then i tried to change the OOO settings which recommended on ooo forums.
1) Change HTML compatibility - character set UTF-8 which should fix the problem but it havn't
2) Then change the Language settings -> set Locale for Russian and the bug fixes.
see the screen shot
Preferences
During my annual vacation, colleague could not manage to change the preferences to the production server. He as usual connect to server by ssl client on cli mode and thus could't change to the preferences. We usually use winscp or standard ssl client to connect to remote Solaris server. There are another very well tools xManager which will help you to bring remote linux/unix desktop to your windows desktop. Another very useful command is display LocalIP to tunneling gui from remote computer to local.
DISPLAY=HOST:0.0, export DISPLAY

For that remote port should be open for you to tunneling.
My colleague found another very quick fix to solve the problem with encoding. Through winscp he connects to the remote server and change the default locale to Russian by the following code on Linguistic.xcu file. Here is the fragments of the file to change
<node oor:name="General">

<prop oor:name="DefaultLocale" oor:type="xs:string">

<value>ru-RU</value>

</prop>

</node>

lingusitic.xcu file should be found on Solris file systme ~/.openoffice.org/3/user/registry/data/org/openoffice/Office/Linguistic.xcu

Monday

Ibatis3 with oracle proxy authentication

Most of all oracle security features could be done by oracle proxy authentication. Oracle proxy authentication provides fine grained access control for temporary users of the account, without compromising the original password even enabling database auditing and logging. In this current post i will first setup database for proxy authentication and later will connect to it by connection pool.

1) Database setup:
sqlplus /nolog
conn sys/manager@orcl as sysdba

create a proxy user
create user          proxy_user
identified by        pw_proxy
default tablespace   users
temporary tablespace temp;

create a target user
create user          target_user
identified by        pw_target
default tablespace   users
temporary tablespace temp
quota unlimited on   users;

now we will alter target user to connect through proxy user
alter user target_user grant connect through proxy_user;

Also grant create session and the create table system privilege
grant create session,
create table
to    target_user;

Note that only target user has connect session privilege. Now we will create one table for demonstration purpose and insert some data on it.
connect target_user/pw_target;

create table FDC_OWNERSHIP (
name  varchar2(200)
);
insert into FDC_OWNERSHIP values ('val1');
insert into FDC_OWNERSHIP values ('val2');
insert into FDC_OWNERSHIP values ('val3');
commit;

Now proxy user could connect with syntax proxy_user[targer_user]
connect proxy_user[target_user]/pw_proxy;
select count(*) from FDC_OWNERSHIP;

All our database setup completed, now we can care about ibatis3. For demonstration purpose we will create a Mapper interface and a connection factory class for get the proxy connection.
public interface LsaDbSqlMapper {
@Select("select own.name from ${schemaName}.FDC_OWNERSHIP own")
List orgNames (@Param("schemaName") final String schemName);
}

Here is the quick implemention of the connection factory class:
public class LsaSessionFactory {
private LsaSessionFactory() {    }
private static SqlSessionFactory sessionFactory;
private static OracleOCIConnectionPool ociPool;

private static String tnsAlias = "(DESCRIPTION =\n" +
"    (ADDRESS_LIST =\n" +
"      (ADDRESS = (PROTOCOL = TCP)(HOST = 172.24.10.57)(PORT = 1521))\n" +
"    )\n" +
"    (CONNECT_DATA =\n" +
"      (SERVICE_NAME = xyz)\n" +
"    )\n" +
"  )";

private static DataSource getOciDataSource(String username, String password) throws SQLException{
if(ociPool == null){
ociPool = new OracleOCIConnectionPool();
ociPool.setURL("jdbc:oracle:oci:@"+ tnsAlias);
ociPool.setUser(username);
ociPool.setPassword(password);
Properties prop = new Properties();
prop.setProperty(OracleOCIConnectionPool.CONNPOOL_MIN_LIMIT, "3");
prop.setProperty(OracleOCIConnectionPool.CONNPOOL_MAX_LIMIT, "5");
prop.setProperty(OracleOCIConnectionPool.CONNPOOL_INCREMENT, "1");
ociPool.setPoolConfig(prop);
}

return ociPool;
}
public static SqlSessionFactory getSessionFactory(String username, String password){
if(sessionFactory == null){
try {
Environment env = new Environment("Development", new JdbcTransactionFactory(),getOciDataSource(username, password));
Configuration config = new Configuration(env);
config.addMapper(LsaDbSqlMapper.class);

sessionFactory = new SqlSessionFactoryBuilder().build(config);
} catch (SQLException e) {
e.printStackTrace();
}
}
return sessionFactory;
}

public static Connection getProxyConnection(String proxyUserName) throws SQLException{
if(ociPool != null ){
Properties userNameProp = new Properties();
userNameProp.setProperty(OracleOCIConnectionPool.PROXY_USER_NAME,proxyUserName);
return ociPool.getProxyConnection(OracleOCIConnectionPool.PROXYTYPE_USER_NAME, userNameProp);
}
return null;
}
public static void closePool() throws SQLException{
if(ociPool != null){
ociPool.close();
}
}
}

Here is the simple test of the connection factory
public class Service {
public static void main(String[] args) throws Exception{
System.out.println("Test Proxy authentication ...");
SqlSession session = LsaSessionFactory.getSessionFactory("PROXY_USER","pw_proxy").openSession(LsaSessionFactory.getProxyConnection("target_user"));
LsaDbSqlMapper sqlMapper = session.getMapper(LsaDbSqlMapper.class);
List orgNames = sqlMapper.orgNames("eos");
System.out.println("Orgs:"+ orgNames);

LsaSessionFactory.closePool();
}


References:
1) Effective Oracle Database 10g Security by Design
2) René Nyffenegger's collection of things on the web
3) Using Oracle Proxy Authentication with JPA (EclipseLink-Style)

Wednesday

Writing weblogic logs to database table

By default, oracle weblogic server logging service uses an implementation, based on the Java Logging APIs by using the LogMBean.isLog4jLoggingEnabled attribute. With a few effort you can use log4j with weblogic logging service. In the Administration Console, you can specify Log4j or keep the default Java Logging implementation. In this blog i will describe how to configure log4j with weblogic logging service and writes all the logs messages to database table.
Most of all cases it's sufficient to writes log on files, however it's better to get all the logs on table to query on it. In our case we have 3 different web logic servers in our project and our consumer need to get all the logs in one central place to diagnose if something goes wrong.
First of all we will create a simple table on our oracle database schema and next configure all other parts.
Here we go:
1)
CREATE TABLE LOGS
(USER_ID VARCHAR2(20),
DOMAIN  varchar2(50),
DATED   DATE NOT NULL,
LOGGER  VARCHAR2(500) NOT NULL,
LEVEL   VARCHAR2(50) NOT NULL,
MESSAGE VARCHAR2(4000) NOT NULL
);

2) Now we will create a log4j.properties file with following contents and save it %DOMAIN_HOME%
log4j.rootLogger=INFO, DB
log4j.logger.com.bea.weblogic.*=INFO, DB

log4j.appender.DB=org.apache.log4j.jdbc.JDBCAppender
# Set JDBC URL
log4j.appender.DB.URL=jdbc:oracle:thin:@mercury.blu.com:1521:FTSDB
# Set Database Driver
log4j.appender.DB.driver=oracle.jdbc.OracleDriver
# Set database user name and password
log4j.appender.DB.user=xyz
log4j.appender.DB.password=xyz
# Set the SQL statement to be executed.
log4j.appender.DB.sql=INSERT INTO EXT_LOGS VALUES('%x','OSB_DOMAIN',sysdate,'%C','%p','%m')
log4j.appender.DB.layout=org.apache.log4j.PatternLayout
#log4j.appender.DB.layout.ConversionPattern=%d{dd.mm.yyyy HH:mm:ss.SSS} - %m%n

3) Copy log4j-1.2.9.jar & wllog4j.jar and ojdbc14.jar under domain_root/lib folder.
4) edit setDomainEnv.sh with following JAVA_OPTION parameter
set JAVA_OPTIONS=-Dweblogic.log.Log4jLoggingEnabled=true
which will active log4j for logging service
5) Most critical tips, add following parameter after JAVA_OPTIONS
set LOG4J_CONFIG_FILE=%DOMAIN_HOME%/log4j.properties
which will force weblogic server to read the log4j configure file from the specified location.
6) Restart the server and you should find all the log messages on database table.
You may also use custom connection pool mechanism with a little effort with JDBCAppender.

Friday

Configure apache CXF project to deploy on Weblogic server 10.3.2.0

Last week we have migrated our one of web service project on apache CXF. Apache CXF provides simplified security package to authentication and authorization for web services. As usual we decided to use Weblogic as our favorite application server to deploy and run migrated service. This blog post is consist of a few tips to configure properly Apache CXF project to deploy on Weblogic server. Most of all tips i have got from the following link JAX-WS, CXF and SAAJ on Oracle Weblogic 10.3, but it was not sufficient to deploy successfully, a few additional task needed to deploy Apcahe CXF on Weblogic. This current post is all about this tips.

First of all we must configure and prepare Apache CXF project to deploy.
1) Add the following fragment of xml configuration to you weblogic.xml
<container-descriptor>
<prefer-web-inf-classes>true</prefer-web-inf-classes>
</container-descriptor>

which will force weblogic to use library from WEB-INF/lib. By default Apache CXF uses geronimo jax-ws implementations to execute webservices.
2) Add javax.jws.* package name into prefer-application-packages as follows:
<wls:prefer-application-packages>
<wls:package-name>antlr.*</wls:package-name>
<wls:package-name>org.apache.*</wls:package-name>
<wls:package-name>org.joda.time.*</wls:package-name>
<wls:package-name>javax.jws.*</wls:package-name>
</wls:prefer-application-packages>

3) Exclude a few libraries from WEB-INF/lib:
saaj-api and it's implementation saaj-impl. Because of conflict with weblogic saaj-api-1.1.jar. You can exclude these two jars through maven dependencies exclusion feature or through maven-war-plugin.
to avoid this following error
"weblogic.xml.jaxp.RegistrySAXParserFactory cannot be cast to javax.xml.parsers.SAXParserFactory"
you should also exclude xml-apis-*.jar from WEB-INF/lib directory.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webResources>
<resource>
<directory>src/main/webapp</directory>
<filtering>true</filtering>
</resource>
</webResources>
<attachClasses>true</attachClasses>
<packagingExcludes>WEB-INF/lib/saaj-api*.jar, WEB-INF/lib/xml-apis-*.jar</packagingExcludes>
</configuration>
</plugin>

After archiving into ear archive it's time to configure Weblogic system properties to deploy.
In a few words you should add the following system property
"-Djavax.xml.soap.MessageFactory=com.sun.xml.internal.messaging.saaj.soap.ver1_1.SOAPMessageFactory1_1Impl" into Weblogic startup script or setDomainEnv.sh.
This will enable the JSE6 saaj implementation for Weblogic server.

Thursday

JODReports is alive

Yesterday we got a requirement from our consumer to convert MS office document to Html as like a google feature "View as html" on portal. As always it was very urgent and with high priority task on Jira. At first i have tried to solve it on regular way but found that there is no straight forword way on java to manage the task. A few commercial product has available on the web to solve the task. One of them are Davisor, 1 cpu license is about 2400 euro. Another one is Aspose. Download their trail version and first of all i discover that Aspose has not support convert Pdf to Html. Davisor convert MS office document not very well, nested table couldn't convert to html at all.
After a few googling i have found some information to use Open Office Org (ooo) to convert MS office documents to any format including PDF, html e.t.c. Also found a few fragment of code and API documents of OOO and JODConvertor open source to convert MS office documents. With great surprise i found that JOdConverter implements OOO api and it's out of box api to convert documents.
JODconverter library provides:
1) CLI to convert documents from command line
2) High level Java api
3) Web service to convert documents
4) Maven 2 plugin
JodReports even provides very well documented user guide to quick start. All you have to need is to start Open office application as and service and you are ready to go.
For starting OOO follow the command
ip-95-221-157-44:~ samim$ /Applications/OpenOffice.org.app/Contents/MacOS/soffice -accept="socket,host=localhost,port=8100;urp;" -nologo -headless

Now you are ready to make some experiment with MS office documents,
OpenOfficeConnection conn = new SocketOpenOfficeConnection(8100);
try {
conn.connect();
DocumentConverter converter = new OpenOfficeDocumentConverter(conn);
converter.convert(new File("/Users/samim/Downloads/big.doc"), new File("/Users/samim/Downloads/big.html"));
} catch (ConnectException e) {
e.printStackTrace();
} finally {
conn.disconnect();
}

You could also customize your export options whenever convert to PDF documents. JOdConverter save my a lot of time and solve my task and satisfy our customer. Many thank't to the developers of the library.

Saturday

Playing with Ibatis *.*Provider to create dynamic query

Last week, in one of our project, which we decided to upgrade sql queries on ibatis needed dynamic sql query execution. As we decided to use annotations as much as possible on sql mapper - it's seems not a straight to build dynamic query. At first tried to do something as follows:
DONOT TRY THIS - IT'S WRONG WAY TO BUILD DYNAMIC QUERY
@Update("update ${schemaName}.fdc_uf uf" +
" set uf.reestr_date = #{reestDate}," +
" uf.reestr_number = #{reestNum}" +
" where uf.reestr_number IS NULL AND uf.reestr_date IS NULL and uf.id in " +
" <foreach item="item" index="index" collection="list" open="(" separator="," close=")">"+
" #{item}"+
" </foreach>")

After some tries, read the user guide attentively, found there are another a few way to build dynamic query, one of them to use Select/Insert/UpdateProvider.
These alternative SQL annotations allow you to specify a class name and a method that will return the SQL to run at execution time. Upon executing the mapped statement, iBATIS will instantiate the class, and execute the method, as specified by the provider.
Here is the required steps to achieve the goals:
1) First we will create the Builder to build the sql
package com.blue.ibatis.test.dao;

import java.sql.Date;
import java.util.List;
import java.util.Locale;
import java.text.DateFormat;
import java.text.SimpleDateFormat;

import static org.apache.ibatis.jdbc.SelectBuilder.*;
//import static org.apache.ibatis.jdbc.SqlBuilder.*;
public class SqlBuilder {

public String simpleUpdate(final FdcUf fdcUf){
final DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM, new Locale("ru"));
String date = df.format(fdcUf.getReestrDate());
StringBuilder sql= new StringBuilder("update fdc_uf uf " +
" set uf.reestr_number = '"+fdcUf.getReestrNom()+"' ," +
" uf.reestr_date = to_date('"+ date+"',"+" '"+getDatePattern()+"')"+
" where uf.id in (") ;
for(Long l : fdcUf.getIds()){
sql.append(l);
sql.append(",");
}
sql.deleteCharAt(sql.lastIndexOf(","));
sql.append(")");
System.out.println("Sql:"+ sql.toString());

return sql.toString();
}
public String getufById(long id){
return "select uf.nom_uf from fdc_uf uf where uf.id="+id;    
}
private String getDatePattern(){
return ((SimpleDateFormat)DateFormat.getDateInstance(DateFormat.MEDIUM, new Locale("ru"))).toPattern();
}
}

Ibatis user guide offers SelectBuilder and SqlBuilder class to build sql queries dynamical. I have found the SelectBuilder but couldn't found the SqlBuilder. For that reason uses Stringbuilder on above code fragment.

See the screen shot from the user guide about SqlBuilder, but i havn't found it.
Now we have to Edit Mapper class.
@UpdateProvider(type = com.blue.ibatis.test.dao.SqlBuilder.class, method = "simpleUpdate")
void simpleUpdate(final FdcUf fdcUf);

and we are ready to invoke mapper.
Here is the simple pojo of the FdcUf

package com.blue.ibatis.test.dao;

import java.sql.Date;
import java.util.List;

public class FdcUf {
private long id;
private String reestrNom;
private Date reestrDate;
private List <long> ids;
public FdcUf() {
}

public long getId() {
return id;
}

public void setId(long id) {
this.id = id;
}

public String getReestrNom() {
return reestrNom;
}

public void setReestrNom(String reestrNom) {
this.reestrNom = reestrNom;
}

public Date getReestrDate() {
return reestrDate;
}

public void setReestrDate(Date reestrDate) {
this.reestrDate = reestrDate;
}

public List <long> getIds() {
return ids;
}

public void setIds(List<long> ids) {
this.ids = ids;
}
}


Happy Coding

Thursday

Call pl/sql package by Ibatis 3

Last few weeks i have been working with a project ,where we decided to use Ibatis for generating complex report. Ibatis is a very small smart ORM tools to execute complex query but, in version 3, developers made a vast change and it's difficult to migrate from version 2 to version 3.
In this post i am going to describe how to call pl/sql package function from within Ibatis3.
First of all we will create two small tables and a pl/sql package for demonstration:
-- Create table
create table ADDRESSES
(
ADR_ID      INTEGER not null,
ADR_CITY    VARCHAR2(15),
ADR_COUNTRY VARCHAR2(15) not null
);
alter table ADDRESSES
add primary key (ADR_ID);
create table PERSONS
(
PRS_ID         INTEGER not null,
PRS_FATHER_ID  INTEGER,
PRS_MOTHER_ID  INTEGER,
PRS_ADR_ID     INTEGER,
PRS_FIRST_NAME VARCHAR2(15),
PRS_SURNAME    VARCHAR2(15)
);
/
alter table PERSONS
add constraint PRS_ADR_FK foreign key (PRS_ADR_ID)
references ADDRESSES (ADR_ID);
alter table PERSONS
add constraint PRS_PRS_FATHER_FK foreign key (PRS_FATHER_ID)
references PERSONS (PRS_ID);
alter table PERSONS
add constraint PRS_PRS_MOTHER_FK foreign key (PRS_MOTHER_ID)
references PERSONS (PRS_ID);

create or replace package IbatisTest is

function getPersonsById(p_id integer) return varchar2;
function addPerson(p_name varchar2, p_fname varchar2, p_add integer)return integer;

end IbatisTest;
/
create or replace package body IbatisTest is

function getPersonsById(p_id integer) return varchar2 is
l_name varchar2(200);
begin
select 
p.prs_first_name
into l_name       
from persons p
where p.prs_id = p_id;    

return(l_name);
end;
function addPerson(p_name varchar2, p_fname varchar2, p_add integer)return integer 
is
p_id integer;       
begin
select common_seq.nextval 
into p_id 
from dual;
insert into persons(prs_id, prs_first_name, prs_surname, prs_adr_id) 
values (p_id, p_fname, p_name, p_add) returning prs_id into p_id;
commit;       
return (p_id);
end;  

begin
null;
end IbatisTest;
/

next we we will develop our *Mapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN"
"http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd">
<mapper namespace="com.blue.ibatis.test.dao.FooMapper">
<parameterMap id="parameters1" type="LRU">
<parameter property="name" jdbcType="VARCHAR" javaType="java.lang.String" mode="OUT"/>
<parameter property="id" jdbcType="NUMERIC" javaType="java.lang.Long" mode="IN"/>
</parameterMap>

<parameterMap id="addParameters" type="LRU">
<parameter property="p_id" jdbcType="NUMERIC" javaType="java.lang.Long" mode="OUT"/>
<parameter property="p_name" jdbcType="VARCHAR" javaType="java.lang.String" mode="IN"/>
<parameter property="p_fname" jdbcType="VARCHAR" javaType="java.lang.String" mode="IN"/>
<parameter property="p_add" jdbcType="NUMERIC" javaType="java.lang.Long" mode="IN"/>
</parameterMap>

<select statementType="CALLABLE" id="getPersonsById" parameterMap="parameters1" resultType="String">
{ ? = call IbatisTest.getPersonsById( ? ) }
</select>

<select statementType="CALLABLE" id="addPerson" parameterMap="addParameters" resultType="Integer">
{ ? = call IbatisTest.addPerson( ?,?,? ) }
</select>
</mapper>

and on finish we have a few fragments of java code to call pl/sql package function
// query to addPersons
Map pMap = new HashMap();
pMap.put("p_name","Xyz");
pMap.put("p_fname","qwe");
pMap.put("p_add", Long.valueOf(11l));

session.selectOne("com.blue.ibatis.test.dao.FooMapper.addPerson", pMap);
pMap.get("p_id");