Tuesday, July 07, 2009

ESB Key functions

1) Route messages between different service providers
Example: A message arrives in oracle AQ and a Java service is called as a result

2) Convert the transport protocols
Example: Convert a PL/SQl to Java method call

3) Transform the message
Example: Oracle AQ payload could be a text message, the Java call will take an object parameter, so the ESB should do the transformation

4) Handle business events from different sources
Example: Same Java service can be invoked as a result of a message from oracle AQ or a call from another Java service

Sunday, March 23, 2008

A simple index test using Oracle 10g free edition

Background

I downloaded oracle 10g express edition from http://www.oracle.com/technology/products/database/xe/index.html.

I have a Pentium 4 winxp machine with 1gb ram and 320 gb hdd.

The download and install was a breeze.

It installs as a service and does start up with windows. However it can be stopped from starting up with windows, by using the services tool in the control panel.

When up and running the oracle 10g took around 250 mb ram on my pc.

I do not have toad, but the 10g express edition install comes with SQL command line and also a HTML based UI. The HTML UI though not comparable to Toad, does work alright with the basic tasks.

I wanted to test out a single column index and see if it mad any difference in searches.

The database and data setup

The test table and sequence is as below:-


Sequence details

CREATE SEQUENCE "TASK_LIST_SEQ"
MINVALUE 1 MAXVALUE 999999999999999999999999999
INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE
/

Table details

CREATE TABLE "TASK_LIST"
( "TASK_ID" NUMBER(18,0) NOT NULL ENABLE,
"TASK_NAME" VARCHAR2(100) NOT NULL ENABLE,
"TASK_STATUS" NUMBER(1,0) NOT NULL ENABLE,
CONSTRAINT "TASK_LIST_PK" PRIMARY KEY ("TASK_ID") ENABLE
)
/
CREATE OR REPLACE TRIGGER "BI_TASK_LIST"
before insert on "TASK_LIST"
for each row
begin
select "TASK_LIST_SEQ".nextval into :NEW.TASK_ID from dual;
end;

/
ALTER TRIGGER "BI_TASK_LIST" ENABLE
/


1) The table holds tasks with their id's, name and status.
2) The id is the primary key.
3) The sequence helps with the id generation automatically with the help of a trigger.
4) The column of interest is TASK_STATUS. I have decided to have status of 1 as complete and 0 as not complete.

Now we will do the following with the help of a pl/sql block.

1) Insert 200000 tasks with status 1(complete)
2) Insert 30000 tasks with status 0(not complete).

The code to do so is as below:-


--Insert 200000 tasks with status 1(complete)
declare
task_name_var varchar2(100);
begin
for i in 1..200000 loop
task_name_var := 'Task ' || i;
--DBMS_OUTPUT.PUT_LINE('task_name_var : ' || task_name_var);
Insert into
task_list(task_name, task_status)
values(task_name_var,1);
end loop;
end;

--Insert 30000 tasks with status 0(not complete)
declare
task_name_var varchar2(100);
begin
for i in 200001..230000 loop
task_name_var := 'Task ' || i;
--DBMS_OUTPUT.PUT_LINE('task_name_var : ' || task_name_var);
Insert into
task_list(task_name, task_status)
values(task_name_var,1);
end loop;
end;


The Tests without any index

Test not complete tasks

do a select count for all task not complete

select count(*) from task_list tl where tl.task_status = 0;

The explain plan (click on the image for greater resolution)



Test complete tasks

do a select count for all task complete

select count(*) from task_list tl where tl.task_status =1;

The explain plan (click on the image for greater resolution)



The Tests with index

Add the Index

create index "TASK_STATUS_IDX1"
on "TASK_LIST" ("TASK_STATUS")
/

Test not complete tasks

do a select count for all task not complete

select count(*) from task_list tl where tl.task_status = 0;

The explain plan (click on the image for greater resolution)



Test complete tasks

do a select count for all task complete

select count(*) from task_list tl where tl.task_status =1;

The explain plan (click on the image for greater resolution)



Conclusion

Note:- The number of rows for task complete(task_status - 1) was 200000 and for task not complete(task_status - 0) was 30000.

1) Without the index the time taken by both searches was 3 and cost was 234
2) With the index the time taken by the task complete(task_status - 1) search was 2 and cost was 131
3) With the index the time taken by the task not complete(task_status - 0) search was 1 and cost was 61.
4) The index on task_status column did improve performance.
5) The performance gain was greater for the task_status value with less number of rows i.e. task not complete(task_status - 0).

Friday, August 31, 2007

EJB3 local bean access in servlet using glassfish

I was trying out Glassfish.

I made a separate ear with a stateless bean and a war with a servlet that accesses the stateless bean using @EJB injection. I deployed the ejb jar file and also the servlet war file. It did not work. The error was that the servlet did not find the ejb.

Reading the glassfish docs I came across this question in the glassfish faq.

--------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------

Question: I have an EJB with a Local interface. Can I access it from a web component in a different application?

Answer: No, not in our implementation. The EJB spec only requires local ejb access from within the same application in the same JVM.

--------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------

Actually that makes a lot of sense.

All I needed to do was to have an ear file with both the war and ear as modules. That way the local EJB could be found by the servlet.

Since the servlet needed to access the local interface I also packaged the interface in WEB-INF/lib/ejbinterfaces.jar folder.

serialVersionUID from java 5

I started using eclipse with java 5. I got this a compilation warning in one of the realizable class, which said something to the effect that it needs a 'serialVersionUID' field.


http://www.doc.ic.ac.uk/csg/java/1.5.0docs/api/java/io/Serializable.html


The 'serialVersionUID' field helps with making sure that the version of the class that has been serialized, is the same as the version of the class that is de-serialized and if it is not the a invalidClassException is thrown.

The field looks like 'private static final long serialVersionUID = 42L'.

Since it needs to be a static field, i guess each class and it's subclasses will need have one field per class declared if there is a heirarchy of classes that need to be serialized.

Tuesday, August 21, 2007

Some notes on the new java 1.5 concurrent api

In the new java 1.5 Concurrent api, there is a lock.tryLock method, which returns false if the lock is already acquired by some other thread.

I have been in situations where I needed to know if an object lock(via synchronized(object a)) had already been acquired or not.

I guess it is simple now with the above 1.5 api.

However the other important thing to know is, if an object lock is in wait state or not before calling wait or notify on the lock. The 1.5 api has a Condition interface, but i did not see any kind of isWaiting method.

In java 1.4 i have achieved this by using volatile booleans, setting the boolean just before calling wait and then unsetting the boolean just after the notify.

Since wait and notify need to happen in synchronized blocks, this method has worked. However i would like to have an isWaiting api for locks.

Thursday, November 30, 2006

Big 'O' notation and Java Constant time performance

Big 'O' notation and Java Constant time performance

Collection Constant time performance, in a line is "The same amount of time taken for a certain operation(method) regardless of the number of elements in the collection"

Big 'O' notation

The Big O notation is used to indicate the time taken by algorithms to run :-

For example:-
(N is the number of elements)

O(N):- The time taken is linerarly dependent to the number of elements.

O(log N):- The time taken is logarithmic to the number of elements.

O(1):- The time taken is constant time, regardless of the number of elements.

Please read here to find out about the big O notation:-

http://en.wikipedia.org/wiki/Big_O_notation

In java collections

Sets

1) The HashSet offers constant time performance for basic operations (add, remove, contains and size).

2) The TreeSet provides guaranteed log(n) time cost for the basic operations (add, remove and contains).

3) Like HashSet, the LinkedHashSet provides constant-time performance for the basic operations (add, contains and remove)

Lists

4) The ArrayList offers constant time performance in the size, isEmpty, get, set, iterator, and listIterator operations. The add operation runs in linear time. All of the other operations run in linear time (roughly speaking).

Maps

5) The HashMap provides constant-time performance for the basic operations (get and put).

6) The TreeMap provides guaranteed log(n) time cost for the containsKey, get, put and remove operations.

7) Like HashMap, the LinkedHashMap provides constant-time performance for the basic operations (add, contains and remove), assuming the the hash function disperses elements properly among the buckets.

If you need a List you could use the ArrayList.

If you need a Set use the HashSet or for a sorted set use the TreeSet or an insertion ordered set use the LinkedHashSet.

If you need a Map use the HashMap or for a key sorted map use the TreeMap or a key insertion ordered map use the LinkedHashMap.

Monday, November 27, 2006

Sring 1.1 and map element

Sring 1.1 and map element

In Spring 1.1 the map element has a key and value like this

<map>
<entry key="event">
<value>ss</value>
<ref>ref1</ref>
</entry>
</map>

In the above code there is no way to specify the "key" as an object, it must be a "String" object !

However from spring 1.2x onwards we can do do this

<map>
<entry>
<key-ref>ref1</key-ref>
<value-ref>ref2</value-ref>
</entry>
<map>

In many cases the above is what one would need of a java map.

Tuesday, October 17, 2006

Java 5, EJB 3 Persistence and Hibernate annotations

Java 5, EJB 3 Persistence and Hibernate annotations

I finally decided to try out some code with Java 5 annonations. For this I chose to try hibernate annotations implementation, which implements EJB 3 persistence with some enhanced annotations of its own.

Pre -requisites
1) Java 5 SDK
2) Latest Hibernate jar with dependent libraries from the lib folder of the download.
3) Latest Hibernate annotation jar with dependent libraries from the lib folder of the download.
4) Ant

Domain Objects

The domain objects are Person and Child. The relationship is one-to-many from person to child and many-to-one from Child to person. The java POJO's are fairly straight forward for this, so I will share the xml here.

Person.hbm.xml


<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

<class name="test.suchak.hibernatetest.domainobjects.Person" table="Person">
<id
name="ID"
column="ID"
>
<generator class="sequence">
<param name="sequence">PERSONIDSEQUENCE</param>
</generator>
</id>
<property name="firstName">
<column name="FirstName"/>
</property>
<property name="lastName">
<column name="LastName"/>
</property>

<list name="children" cascade="all" inverse="true">
<key column="parent_id"/>
<index column="child_id"/>
<one-to-many class="test.suchak.hibernatetest.domainobjects.Child"/>
</list>

</class>

</hibernate-mapping>


Child.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

<class name="test.suchak.hibernatetest.domainobjects.Child" table="Child">
<id
name="child_id"
column="child_id"
>
<generator class="sequence">
<param name="sequence">CHILDIDSEQUENCE</param>
</generator>
</id>
<property name="name">
<column name="name"/>
</property>
<property name="age">
<column name="age"/>
</property>
<many-to-one name="person"
column="parent_id"
class="test.suchak.hibernatetest.domainobjects.Person"
cascade="all"
/>
</class>

</hibernate-mapping>



XML Session factory configuration
The session factry configuration here is prettty simple. Just read the hbm files and pass them to the hibernate configugation.

public class MyHibernateSessionFactory {
......
private void buildSessionFactory(String[] fileNames) {

Configuration config = new Configuration();

for(int i=0;i<filenames.length;i++){
config.addFile(hbmDir + File.separator + fileNames[i]);
}
sessionFactory = config.buildSessionFactory();
} ....
}


Now the sessionFactory.openSession() method will retun the sessions we need. Using the session we can now do CRUD on the child and person POJO's, in the traditional hibernate world.

Annotations

Now instead of the xml files we will use annotations for the same two POJO's person and child.

Person.java


package test.suchak.hibernatetest.domainobjects;

import java.util.List;
//import javax.persistence.*;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.OneToMany;
import javax.persistence.Id;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;
import org.hibernate.annotations.MapKey;
import javax.persistence.CascadeType;

/**
* @author Suchak.Jani
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Style - Code Templates
*
*/

@Entity
@Table(name="Person")
public class Person {
private Integer ID;
private String firstName;
private String lastName;
private List children;

public Person(){

}
/**
* @param firstName2
* @param lastName2
*
*/
public Person(String firstName, String lastName) {
this.firstName=firstName;
this.lastName=lastName;
}

/**
* @return Returns the firstName.
*/
@Column(name = "FirstName")
public String getFirstName() {
return firstName;
}
/**
* @return Returns the iD.
*/
@Id @GeneratedValue(generator="sequence")
@GenericGenerator(name="sequence", strategy = "sequence",
parameters = {
@Parameter(name="sequence", value="PERSONIDSEQUENCE")
}
)
public Integer getID() {
return ID;
}
/**
* @return Returns the lastName.
*/
@Column(name = "LastName")
public String getLastName() {
return lastName;
}
/**
* @param firstName The firstName to set.
*/
public void setFirstName(String firstName) {
this.firstName = firstName;
}
/**
* @param id The iD to set.
*/
public void setID(Integer id) {
ID = id;
}
/**
* @param lastName The lastName to set.
*/
public void setLastName(String lastName) {
this.lastName = lastName;
}

/**
* @return Returns the children.
*/
@OneToMany(mappedBy="person", cascade=CascadeType.ALL)
//@OneToMany(mappedBy="person")
@MapKey(columns=@Column(name="child_id"))
public List getChildren() {
return children;
}
/**
* @param children The children to set.
*/
public void setChildren(List children) {
this.children = children;
}
}


Child.java


package test.suchak.hibernatetest.domainobjects;

//import javax.persistence.*;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.ManyToOne;
import javax.persistence.JoinColumn;
import javax.persistence.Id;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;

/**
* @author Suchak.Jani
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Style - Code Templates
*/
@Entity
@Table(name="Child")
public class Child {

private Integer child_id; // ID
private String name;
private Integer age;
private Person person;


// need a default cosntructor for hibernate to be able to read for this object
public Child() {

}

/**
* @param parent_id2
* @param name2
* @param age2
*/
public Child(Person person,String name, Integer age) {

this.setPerson(person);
this.setName(name);
this.setAge(age);
}
/**
* @return Returns the age.
*/
@Column(name = "age")
public Integer getAge() {
return age;
}
/**
* @param age The age to set.
*/
public void setAge(Integer age) {
this.age = age;
}
/**
* @return Returns the child_id.
*/
@Id @GeneratedValue(generator="sequence")
@GenericGenerator(name="sequence", strategy = "sequence",
parameters = {
@Parameter(name="sequence", value="CHILDIDSEQUENCE")
}
)
public Integer getChild_id() {
return child_id;
}
/**
* @param child_id The child_id to set.
*/
public void setChild_id(Integer child_id) {
this.child_id = child_id;
}
/**
* @return Returns the name.
*/
@Column(name = "name")
public String getName() {
return name;
}
/**
* @param name The name to set.
*/
public void setName(String name) {
this.name = name;
}

/**
* @return Returns the person.
*/
@ManyToOne
@JoinColumn(name="parent_id",nullable=false)
public Person getPerson() {
return person;
}
/**
* @param person The person to set.
*/
public void setPerson(Person person) {
this.person = person;
}
}


Annotation Session factory configuration

The session factry configuration here is different than the xml session factory as shown below.


public class AnnotationHibernateSessionFactory {
....
/**
* @param files
*/
private void buildSessionFactory() {
try {
sessionFactory = new AnnotationConfiguration()
.addAnnotatedClass(Person.class)
.addAnnotatedClass(Child.class)
.buildSessionFactory();
} catch (Throwable ex) {
// Log exception!
throw new ExceptionInInitializerError(ex);
}
}


Key Points

1) XML files not needed.
2) An import per annotation used in the POJO.
3) (inverse="true") is now equivalent to mappedBy.
4) Most annotations are in javax.persistence package.
5) The new AnnotationConfiguration class is to be used instead of the Configuartion class.
6) The xml tags class and class name are not necessary.

Code

The working code is available for download below.

hibernatejdk5test
hibernatejdk5test....
Hosted by eSnips

Java and unsigned numbers

Java and unsigned numbers

Recently there was a requirement for some binnary data read/write work. I started out with some java code. I used the nio ByteBuffer to read and write data.

Something was not right. Whenever i tried to read some sample data the values were right at times and wrong(negative) at other times.

Then a senior consultant colleague, reminded me that all java numbers are 2's complement. In short the MSB(most significant bit) is used to indicate positive or negative number. For further details on 2's complement, please read http://en.wikipedia.org/wiki/Two's_complement .

That sent me on a trail to firgure out how could i read/write an unsigned number using java.

The basic understanding is that you use a bigger number to store the smaller signed number. That way the bigger signed number becomes the unsigned smaller number.

For example a byte is 8 bits. Its range in java is +127 to -128. (Please read up on the 2's complement bit to understand how we get the negative number)

0111 1111 = 127
1000 0000 = - 128 (2's complement)

So in order to convert this byte to unsinged byte we will incease the byte to a short.

A short in java is 16 bits

0000 0000 0000 0000 0111 1111 = 127
0000 0000 0000 0000 1000 0000 = 128

Here is some code to test this

public class Test {
public static void main(String args[]) {
byte b = -128;
short s = (short)(0x00FF & b);
System.out.println("Byte b = " + b);
System.out.println("Short s = " + s);
}
}

The Result is
D:\>java Test
Byte b = -128
Short s = 128

Please note that i have not directly casted to a short, instead i have done a bit and operation with all 1's (F in hex is 1111 in binary). That way the number is preserved at the byte level. If i had just cast it to a short then java would have treated it as a neagtive number i.e. it still would be -128.

Here is a link that explains clearly how to use binary opreations to achieve this for all number types - http://www.darksleep.com/player/JavaAndUnsignedTypes.html and also Java's integer sizes - http://www.scism.sbu.ac.uk/jfl/Appa/appa1.html

Why does java have no unsigned numbers ?

Sean R. Owens at http://www.darksleep.com/player/JavaAndUnsignedTypes.html, digs up old emails and interviews about Java and Oak where James Gosling explains this :-

http://www.gotw.ca/publications/c_family_interview.htm

Gosling: For me as a language designer, which I don't really count myself as these days, what "simple" really ended up meaning was could I expect J. Random Developer to hold the spec in his head. That definition says that, for instance, Java isn't -- and in fact a lot of these languages end up with a lot of corner cases, things that nobody really understands. Quiz any C developer about unsigned, and pretty soon you discover that almost no C developers actually understand what goes on with unsigned, what unsigned arithmetic is. Things like that made C complex. The language part of Java is, I think, pretty simple. The libraries you have to look up.

Finally Java has no unsigned numbers and when dealing with binary data which might contain unsigned numbers, one has to keep this fact in mind.