Friday, 23 April 2010

Coherence: Adding my Own POF Serializer for java.sql.Date

The standard serializers that come with POF unfortunately don't cover all standard Java classes. So in this case I have a domain model based on an oracle RDBMS table which was using a DATE column. in Oracle JDBC then we would call getDate() from the ResultSet Object to return a java.sql.Date(). Thanks to some help internally I was able to add my own POF Serializer as shown below.

1. Create a POF Serializer class as follows.


package pas.au.coherence.query.server;

import com.tangosol.io.pof.PofReader;
import com.tangosol.io.pof.PofSerializer;
import com.tangosol.io.pof.PofWriter;

import java.io.IOException;

public class SQLDateSerializer implements PofSerializer
{
public void serialize(PofWriter pofWriter, Object o) throws IOException
{
java.sql.Date d = (java.sql.Date)o;
pofWriter.writeLong(1, d.getTime());
pofWriter.writeRemainder(null);
}

public Object deserialize(PofReader pofReader) throws IOException
{
java.sql.Date result = new java.sql.Date(pofReader.readLong(1));
pofReader.readRemainder();
return result;
}

}

2. Update my POF config file to add this serializer.


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE pof-config PUBLIC "pof-config" "pof-config.dtd" >
<pof-config>
<user-type-list>
<include>coherence-pof-config.xml</include>
<user-type>
<type-id>1000</type-id>
<class-name>pas.au.coherence.query.server.AllDBObject</class-name>
</user-type>
<user-type>
<type-id>1001</type-id>
<class-name>java.sql.Date</class-name>
<serializer>
<class-name>pas.au.coherence.query.server.SQLDateSerializer</class-name>
<init-params/>
</serializer>
</user-type>
</user-type-list>
</pof-config>


3. My domain object would then use read/write object to trigger the use of this serializer

 
package pas.au.coherence.query.server;


import com.tangosol.io.pof.PofReader;
import com.tangosol.io.pof.PofWriter;
import com.tangosol.io.pof.PortableObject;

import java.io.IOException;

import java.math.BigDecimal;

import java.sql.Date;

public class AllDBObject implements PortableObject
{
private String owner;
private String objectName;
private String subObjectName;
private BigDecimal objectId;
private BigDecimal dataObjectId;
private String objectType;
private Date created;
private Date lastDDLTime;
private String timestamp;
private String status;
private String temporary;
private String generated;
private String secondary;
private BigDecimal namespace;
private String editionName;

public AllDBObject()
{
}

public AllDBObject(String owner, String objectName, String subObjectName,
BigDecimal objectId, BigDecimal dataObjectId,
String objectType, Date created, Date lastDDLTime,
String timestamp, String status, String temporary,
String generated, String secondary,
BigDecimal namespace, String editionName)
{
super();
this.owner = owner;
this.objectName = objectName;
this.subObjectName = subObjectName;
this.objectId = objectId;
this.dataObjectId = dataObjectId;
this.objectType = objectType;
this.created = created;
this.lastDDLTime = lastDDLTime;
this.timestamp = timestamp;
this.status = status;
this.temporary = temporary;
this.generated = generated;
this.secondary = secondary;
this.namespace = namespace;
this.editionName = editionName;
}

public void setOwner(String owner)
{
this.owner = owner;
}

public String getOwner()
{
return owner;
}

public void setObjectName(String objectName)
{
this.objectName = objectName;
}

public String getObjectName()
{
return objectName;
}

public void setSubObjectName(String subObjectName)
{
this.subObjectName = subObjectName;
}

public String getSubObjectName()
{
return subObjectName;
}

public void setObjectId(BigDecimal objectId)
{
this.objectId = objectId;
}

public BigDecimal getObjectId()
{
return objectId;
}

public void setDataObjectId(BigDecimal dataObjectId)
{
this.dataObjectId = dataObjectId;
}

public BigDecimal getDataObjectId()
{
return dataObjectId;
}

public void setObjectType(String objectType)
{
this.objectType = objectType;
}

public String getObjectType()
{
return objectType;
}

public void setCreated(Date created)
{
this.created = created;
}

public Date getCreated()
{
return created;
}

public void setLastDDLTime(Date lastDDLTime)
{
this.lastDDLTime = lastDDLTime;
}

public Date getLastDDLTime()
{
return lastDDLTime;
}

public void setTimestamp(String timestamp)
{
this.timestamp = timestamp;
}

public String getTimestamp()
{
return timestamp;
}

public void setStatus(String status)
{
this.status = status;
}

public String getStatus()
{
return status;
}

public void setTemporary(String temporary)
{
this.temporary = temporary;
}

public String getTemporary()
{
return temporary;
}

public void setGenerated(String generated)
{
this.generated = generated;
}

public String getGenerated()
{
return generated;
}

public void setSecondary(String secondary)
{
this.secondary = secondary;
}

public String getSecondary()
{
return secondary;
}

public void setNamespace(BigDecimal namespace)
{
this.namespace = namespace;
}

public BigDecimal getNamespace()
{
return namespace;
}

public void setEditionName(String editionName)
{
this.editionName = editionName;
}

public String getEditionName()
{
return editionName;
}

public void readExternal(PofReader in) throws IOException
{
this.owner = in.readString(0);
this.objectName = in.readString(1);
this.subObjectName = in.readString(2);
this.objectId = in.readBigDecimal(3);
this.dataObjectId = in.readBigDecimal(4);
this.objectType = in.readString(5);
this.created = (Date) in.readObject(6);
this.lastDDLTime = (Date) in.readObject(7);
this.timestamp = in.readString(8);
this.status = in.readString(9);
this.temporary = in.readString(10);
this.generated = in.readString(11);
this.secondary = in.readString(12);
this.namespace = in.readBigDecimal(13);
this.editionName = in.readString(14);
}

public void writeExternal(PofWriter out) throws IOException
{
out.writeString(0, this.owner);
out.writeString(1, this.objectName);
out.writeString(2, this.subObjectName);
out.writeBigDecimal(3, this.objectId);
out.writeBigDecimal(4, this.dataObjectId);
out.writeString(5, this.objectType);
out.writeObject(6, this.created);
out.writeObject(7, this.lastDDLTime);
out.writeString(8, this.timestamp);
out.writeString(9, this.status);
out.writeString(10, this.temporary);
out.writeString(11, this.generated);
out.writeString(12, this.secondary);
out.writeBigDecimal(13, this.namespace);
out.writeString(14, this.editionName);
}

@Override
public String toString()
{
return "AllDbObject - owner: " + this.owner +
" ,objectName: " + this.objectName +
" ,subObjectName: " + this.subObjectName +
" ,objectId: " + this.objectId +
" ,dataObjectId: " + this.dataObjectId +
" ,objectType: " + this.objectType +
" ,created: " + this.created +
" ,lastDDLTime: " + this.lastDDLTime +
" ,timestamp: " + this.timestamp +
" ,status: " + this.status +
" ,temporrary: " + this.temporary +
" ,generated: " + this.generated +
" ,secondary: " + this.secondary +
" ,namespace: " + this.namespace +
" ,editionName: " + this.editionName;
}

@Override
public boolean equals(Object object)
{
if (this == object)
{
return true;
}
if (!(object instanceof AllDBObject))
{
return false;
}
final AllDBObject other = (AllDBObject) object;
if (!(owner == null ? other.owner == null : owner.equals(other.owner)))
{
return false;
}
if (!(objectName == null ? other.objectName == null : objectName.equals(other.objectName)))
{
return false;
}
if (!(subObjectName == null ? other.subObjectName == null : subObjectName.equals(other.subObjectName)))
{
return false;
}
if (!(objectId == null ? other.objectId == null : objectId.equals(other.objectId)))
{
return false;
}
if (!(dataObjectId == null ? other.dataObjectId == null : dataObjectId.equals(other.dataObjectId)))
{
return false;
}
if (!(objectType == null ? other.objectType == null : objectType.equals(other.objectType)))
{
return false;
}
if (!(created == null ? other.created == null : created.equals(other.created)))
{
return false;
}
if (!(lastDDLTime == null ? other.lastDDLTime == null : lastDDLTime.equals(other.lastDDLTime)))
{
return false;
}
if (!(timestamp == null ? other.timestamp == null : timestamp.equals(other.timestamp)))
{
return false;
}
if (!(status == null ? other.status == null : status.equals(other.status)))
{
return false;
}
if (!(temporary == null ? other.temporary == null : temporary.equals(other.temporary)))
{
return false;
}
if (!(generated == null ? other.generated == null : generated.equals(other.generated)))
{
return false;
}
if (!(secondary == null ? other.secondary == null : secondary.equals(other.secondary)))
{
return false;
}
if (!(namespace == null ? other.namespace == null : namespace.equals(other.namespace)))
{
return false;
}
if (!(editionName == null ? other.editionName == null : editionName.equals(other.editionName)))
{
return false;
}
return true;
}

@Override
public int hashCode()
{
final int PRIME = 37;
int result = 1;
result = PRIME * result + ((owner == null) ? 0 : owner.hashCode());
result = PRIME * result + ((objectName == null) ? 0 : objectName.hashCode());
result = PRIME * result + ((subObjectName == null) ? 0 : subObjectName.hashCode());
result = PRIME * result + ((objectId == null) ? 0 : objectId.hashCode());
result = PRIME * result + ((dataObjectId == null) ? 0 : dataObjectId.hashCode());
result = PRIME * result + ((objectType == null) ? 0 : objectType.hashCode());
result = PRIME * result + ((created == null) ? 0 : created.hashCode());
result = PRIME * result + ((lastDDLTime == null) ? 0 : lastDDLTime.hashCode());
result = PRIME * result + ((timestamp == null) ? 0 : timestamp.hashCode());
result = PRIME * result + ((status == null) ? 0 : status.hashCode());
result = PRIME * result + ((temporary == null) ? 0 : temporary.hashCode());
result = PRIME * result + ((generated == null) ? 0 : generated.hashCode());
result = PRIME * result + ((secondary == null) ? 0 : secondary.hashCode());
result = PRIME * result + ((namespace == null) ? 0 : namespace.hashCode());
result = PRIME * result + ((editionName == null) ? 0 : editionName.hashCode());
return result;
}
}

Wednesday, 21 April 2010

Oracle Coherence / POF (Portable Object Format) with JDeveloper 11g

Now I am constantly creating coherence projects in JDeveloper 11g as my IDE it has a useful source code wizard. The wizard is "Source -> Generate equals() and hashCode() methods". Given I am more often then not using POF (Portable Object Format) then this option saves me a lot of time. The "Source -> Generate Constructor from fields" also comes in very handy for Coherence projects as well.

From memory JDeveloper 10g didn't have these source code wizard's.

POF is described in the link below. Using POF has many advantages ranging from performance benefits to language independence.

http://coherence.oracle.com/display/COH35UG/The+Portable+Object+Format

Friday, 2 April 2010

Diagnosability Management with the 11g JDBC Driver

The JDBC diagnosability management feature introduces an MBean, oracle.jdbc.driver.OracleDiagnosabilityMBean. This MBean provides means to enable and disable JDBC logging. You problematically enable it as shown bythe method "enableOracleLogging()"from the code below.

1. First ensure you are using the debug version of the Orace JDBC driver. Given I was using JDK 1.6 I used ojdbc6_g.jar

2. Ensure you register the JDBC driver prior to enabling logging

DriverManager.registerDriver(new OracleDriver());

3. Full Code demo as follows:


package pas.au.jdbc.logging;

import java.lang.management.ManagementFactory;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;

import java.sql.Statement;

import java.util.logging.FileHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;

import javax.management.Attribute;
import javax.management.MBeanServer;
import javax.management.ObjectName;

import oracle.jdbc.OracleDriver;


public class Test
{
public Test()
{
}

public void run () throws SQLException
{
DriverManager.registerDriver(new OracleDriver());
enableOracleLogging();
Connection conn = null;
Statement stmt = null;
ResultSet rset = null;

try
{
conn = getConnection();
System.out.println("Connection retrieved..");

stmt = conn.createStatement();
rset = stmt.executeQuery("select empno from emp");
while (rset.next())
{
System.out.println(rset.getInt(1));
}
}
catch (SQLException sqle)
{
sqle.printStackTrace();
}
finally
{
if (rset != null)
{
rset.close();
}

if (stmt != null)
{
stmt.close();
}

if (conn != null)
{
conn.close();
}
}


System.out.println("Connection closed");
}

public static Connection getConnection() throws SQLException
{
String username = "scott";
String password = "tiger";
String thinConn =
"jdbc:oracle:thin:@beast.au.oracle.com:1521/linux11g";

Connection conn =
DriverManager.getConnection(thinConn, username, password);
conn.setAutoCommit(false);
return conn;
}

private static void enableOracleLogging()
{
try
{
Handler fh = new FileHandler("./oracle_jdbc_log.log");
fh.setLevel(Level.ALL);
fh.setFormatter(new SimpleFormatter());
Logger.getLogger("").addHandler(fh);
Logger.getLogger("").setLevel(Level.ALL);

MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
String loader = Thread.currentThread().getContextClassLoader().toString().
replaceAll("[,=:\"]+", "");
ObjectName pattern =
new ObjectName("com.oracle.jdbc:type=diagnosability,name=" +
loader );
ObjectName diag = ((ObjectName[])(mbs.queryNames(pattern, null).
toArray(new ObjectName[0])))[0];

mbs.setAttribute(diag, new Attribute("LoggingEnabled", true));
System.out.println("LoggingEnabled = " +
mbs.getAttribute(diag, "LoggingEnabled"));
}
catch(Exception e)
{
e.printStackTrace();
}
}

public static void main(String[] args) throws Exception
{
Test test = new Test();
test.run();
}
}
4. Sample Output as follows, most of it ommitted due to the size of the log file given we asked for everything to be logged.

Apr 2, 2010 10:09:30 AM DefaultMBeanServerInterceptor setAttribute
FINER: Object= com.oracle.jdbc:type=diagnosability,name=sun.misc.Launcher$AppClassLoader@47858e, attribute=LoggingEnabled
Apr 2, 2010 10:09:30 AM Repository retrieve
FINER: name=com.oracle.jdbc:type=diagnosability,name=sun.misc.Launcher$AppClassLoader@47858e
Apr 2, 2010 10:09:30 AM DefaultMBeanServerInterceptor getAttribute
FINER: Attribute= LoggingEnabled, obj= com.oracle.jdbc:type=diagnosability,name=sun.misc.Launcher$AppClassLoader@47858e
Apr 2, 2010 10:09:30 AM Repository retrieve
FINER: name=com.oracle.jdbc:type=diagnosability,name=sun.misc.Launcher$AppClassLoader@47858e
Apr 2, 2010 10:09:30 AM oracle.jdbc.driver.OracleDriver connect
TRACE_1: Public Enter: "jdbc:oracle:thin:@beast.au.oracle.com:1521/linux11g", {user=scott, password=tiger}
Apr 2, 2010 10:09:30 AM oracle.jdbc.driver.OracleDriver oracleDriverExtensionTypeFromURL
TRACE_16: Enter: "jdbc:oracle:thin:@beast.au.oracle.com:1521/linux11g"
Apr 2, 2010 10:09:30 AM oracle.jdbc.driver.OracleDriver oracleDriverExtensionTypeFromURL
TRACE_16: return: 0
Apr 2, 2010 10:09:30 AM oracle.jdbc.driver.OracleDriver oracleDriverExtensionTypeFromURL
TRACE_16: Exit
Apr 2, 2010 10:09:30 AM oracle.jdbc.driver.PhysicalConnection
TRACE_16: Enter: "jdbc:oracle:thin:@beast.au.oracle.com:1521/linux11g", {user=scott, password=tiger}, oracle.jdbc.driver.T4CDriverExtension@cb6009
Apr 2, 2010 10:09:30 AM oracle.jdbc.driver.PhysicalConnection readConnectionProperties
TRACE_16: Enter: "jdbc:oracle:thin:@beast.au.oracle.com:1521/linux11g", {user=scott, password=tiger}
Apr 2, 2010 10:09:30 AM oracle.jdbc.driver.PhysicalConnection getSystemProperty
TRACE_16: Enter: "oracle.jdbc.RetainV9LongBindBehavior", null
Apr 2, 2010 10:09:30 AM oracle.jdbc.driver.PhysicalConnection$1 run
TRACE_16: return: null
Apr 2, 2010 10:09:30 AM oracle.jdbc.driver.PhysicalConnection getSystemProperty
TRACE_16: return: null
Apr 2, 2010 10:09:30 AM oracle.jdbc.driver.PhysicalConnection getSystemProperty
TRACE_16: Exit
Apr 2, 2010 10:09:30 AM oracle.jdbc.driver.PhysicalConnection getSystemProperty
TRACE_16: Enter: "oracle.jdbc.database", null
Apr 2, 2010 10:09:30 AM oracle.jdbc.driver.PhysicalConnection$1 run