Thursday, 24 December 2009

Fast Way to Create a Web Service from an EJB3 Entity

Normally I would create an EJB session bean to expose my Entity queries from my Entity beans, but I thought it would be easier to just create a Java Service Facade and expose that as a web service as shown below.

1. In my project create an "Entity from table" using the new object gallery item in the EJB node. In this example we use the classic DEPT table.
2. Then edit your Dept entity to create another named query as shown below, as well as a toString method to display the bean.

....

@Entity
@NamedQueries({
@NamedQuery(name = "Dept.findAll", query = "select o from Dept o"),
@NamedQuery(name = "Dept.findByDeptno", query = "select o from Dept o where o.deptno = :deptno")
})
public class Dept
implements Serializable

...

@Override
public String toString()
{
return "Dept [" + deptno + ", " + dname + ", " + loc + "]";
}

3. From the EJB new object gallery select "Java Service Facade", in the wizard I only exposed these methods as well as a main method to test it with.
  • public List getDeptFindAll() public
  • public List getDeptFindByDeptno(Long deptno)
4. Add code to the main as follows to ensure the Java Service Facade works.

public static void main(String [] args)
{
final JavaServiceFacade javaServiceFacade = new JavaServiceFacade();
// TODO: Call methods on javaServiceFacade here...
List<Dept> deps = javaServiceFacade.getDeptFindAll();
for (Dept d: deps)
{
System.out.println(d);
}
}

5. Run it to verify it works well. Inside the persistence.xml I edited the following property (eclipselink.logging.level=INFO) to reduce the amount of output we get at runtime.

<persistence-unit name="Model-Test" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>model.Dept</class>
<properties>
<property name="eclipselink.jdbc.driver"
value="oracle.jdbc.OracleDriver"/>
<property name="eclipselink.jdbc.url"
value="jdbc:oracle:thin:@//beast.au.oracle.com:1523/linux11gr2"/>
<property name="eclipselink.jdbc.user" value="scott"/>
<property name="eclipselink.jdbc.password"
value="3E20F8982C53F4ABA825E30206EC8ADE"/>
<property name="eclipselink.logging.level" value="INFO"/>
<property name="eclipselink.target-server" value="WebLogic_10"/>
</properties>
</persistence-unit>

Output:

... [EL Warning]: 2009-12-24 11:48:40.203--Failed to get InitialContext for MBean registration: javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial
Dept [10, ACCOUNTING, NEW YORK]

Dept [20, RESEARCH, DALLAS]
Dept [30, SALES, CHICAGO]

Dept [40, OPERATIONS, BOSTON]

6. Now finally create a web service from the "JavaServiceFacade.java". To do this I simply invoked the "Create Java Web Service" from the object gallery or even easier use it's context menu option "Create Web Service".

Now you can test it using the "Test Web Service Wizard" option from the web service itself as now it is a Web Service as per step #6.

Friday, 18 December 2009

Starting A Coherence Cache Server from ANT

Started setting up some coherence demos through ant, in doing so created a small template to work from which enables me to start a coherence cache server. With this you simply place your source code within the SRC directory and it will compile it, package it (once we add a package task), and run the cache server.

1. Firstly create a directory as follows , adding the files (build.properties, build.xml) and 2 directories (src, lib) as shown below.

Directory Name - start-cache-server

build.properties
build.xml
classes - DIRECTORY
lib - DIRECTORY
src - DIRECTORY

2. Ensure you have ant in your path.

D:\jdev\ant-demos\coherence\start-cache-server>ant -version
Apache Ant version 1.7.0 compiled on December 13 2006

3. Edit build.properties ensuring we set coherence home correctly

# oracle.coherence.home
#
oracle.coherence.home=D:/jdev/coherence/352/coherence

# jvmargs
#
# JVM args to pass into the command at runtime to set heap size etc

jvmargs=-server -showversion -Xms512m -Xmx512m

4. Edit build.xml to look as follows

<?xml version="1.0" encoding="windows-1252" ?>

<project default="run-default" name="demo" basedir=".">

<property file="build.properties"/>

<path id="j2ee.classpath">
<pathelement path="${oracle.coherence.home}/lib/coherence.jar"/>
</path>

<property name="src.dir" value="src"/>
<property name="classes.dir" value="classes"/>
<property name="lib.dir" value="lib"/>
<property name="class.name" value="com.tangosol.net.DefaultCacheServer"/>
<property name="jmxclass.name" value="com.tangosol.net.management.MBeanConnector"/>

<target name="init">
<tstamp/>
<mkdir dir="${classes.dir}"/>
</target>

<target name="clean" description="Clean lib, classes directories">
<delete dir="${classes.dir}"/>
</target>

<target name="compile" description="Compiles classes into ${classes.dir}" depends="init">
<javac srcdir="${src.dir}"
debug="true"
destdir="${classes.dir}"
includes="**/*.java" >
<classpath refid="j2ee.classpath"/>
</javac>
</target>

<target name="run-default" depends="compile" description="Run the cache server">
<echo message="Starting cache server with jvm args : ${jvmargs}"/>
<java classname="${class.name}" fork="true">
<!--
Add system properties as follows
<sysproperty key="tangosol.pof.enabled" value="true"/>
-->

<jvmarg line="${jvmargs}"/>
<classpath>
<path refid="j2ee.classpath"/>
</classpath>
</java>
</target>

<target name="run-jmx" depends="compile" description="Run the JMX enabled cache server">
<echo message="Starting JMX enabled cache server with jvm args : ${jvmargs}"/>
<java classname="${jmxclass.name}" fork="true">
<sysproperty key="tangosol.coherence.management" value="all"/>
<sysproperty key="tangosol.coherence.management.remote" value="true"/>
<sysproperty key="com.sun.management.jmxremote" value="true"/>
<jvmarg line="${jvmargs}"/>
<arg line="-rmi" />
<classpath>
<path refid="j2ee.classpath"/>
</classpath>
</java>
</target>

</project>
5. Run cache server using the ant task shown below.

D:\jdev\ant-demos\coherence\start-cache-server>ant run-default
Buildfile: build.xml

init:
[mkdir] Created dir: D:\jdev\ant-demos\coherence\start-cache-server\classes

compile:

run-default:
[echo] Starting cache server with jvm args : -server -showversion -Xms512m -Xmx512m
[java] java version "1.6.0_07"
[java] Java(TM) SE Runtime Environment (build 1.6.0_07-b06)
[java] Java HotSpot(TM) Server VM (build 10.0-b23, mixed mode)
[java] 2009-12-18 10:15:15.062/0.406 Oracle Coherence 3.5.2/463 (thread=main, member=n/a): Loaded operational configur
ation from resource "jar:file:/D:/jdev/coherence/352/coherence/lib/coherence.jar!/tangosol-coherence.xml"
[java] 2009-12-18 10:15:15.078/0.422 Oracle Coherence 3.5.2/463 (thread=main, member=n/a): Loaded operational override
s from resource "jar:file:/D:/jdev/coherence/352/coherence/lib/coherence.jar!/tangosol-coherence-override-dev.xml"
[java] 2009-12-18 10:15:15.078/0.422 Oracle Coherence 3.5.2/463 (thread=main, member=n/a): Optional configuration overri
de "/tangosol-coherence-override.xml" is not specified
[java] 2009-12-18 10:15:15.093/0.437 Oracle Coherence 3.5.2/463 (thread=main, member=n/a): Optional configuration overri
de "/custom-mbeans.xml" is not specified
[java]
[java] Oracle Coherence Version 3.5.2/463
[java] Grid Edition: Development mode
[java] Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
[java]
[java] 2009-12-18 10:15:15.531/0.875 Oracle Coherence GE 3.5.2/463 (thread=main, member=n/a): Loaded cache configurati
on from "jar:file:/D:/jdev/coherence/352/coherence/lib/coherence.jar!/coherence-cache-config.xml"
[java] 2009-12-18 10:15:16.265/1.609 Oracle Coherence GE 3.5.2/463 (thread=Cluster, member=n/a): Service Cluster joined
the cluster with senior service member n/a
[java] 2009-12-18 10:15:19.515/4.859 Oracle Coherence GE 3.5.2/463 (thread=Cluster, member=n/a): Created a new cluster
"cluster:0xD3FB" with Member(Id=1, Timestamp=2009-12-18 10:15:16.031, Address=10.187.80.135:8088, MachineId=57735, Location=site:
au.oracle.com,machine:papicell-au,process:3708, Role=CoherenceServer, Edition=Grid Edition, Mode=Development, CpuCount=2, SocketCo
unt=1) UID=0x0ABB5087000001259EEC7BBFE1871F98
[java] 2009-12-18 10:15:19.546/4.890 Oracle Coherence GE 3.5.2/463 (thread=Invocation:Management, member=1): Service Man
agement joined the cluster with senior service member 1
[java] 2009-12-18 10:15:19.875/5.219 Oracle Coherence GE 3.5.2/463 (thread=DistributedCache, member=1): Service Distribu
tedCache joined the cluster with senior service member 1
[java] 2009-12-18 10:15:19.953/5.297 Oracle Coherence GE 3.5.2/463 (thread=ReplicatedCache, member=1): Service Replicate
dCache joined the cluster with senior service member 1
[java] 2009-12-18 10:15:19.953/5.297 Oracle Coherence GE 3.5.2/463 (thread=OptimisticCache, member=1): Service Optimisti
cCache joined the cluster with senior service member 1
[java] 2009-12-18 10:15:19.968/5.312 Oracle Coherence GE 3.5.2/463 (thread=Invocation:InvocationService, member=1): Serv
ice InvocationService joined the cluster with senior service member 1
[java] 2009-12-18 10:15:19.968/5.312 Oracle Coherence GE 3.5.2/463 (thread=main, member=1): Started DefaultCacheServer
...
[java]
[java] SafeCluster: Name=cluster:0xD3FB
[java]
[java] Group{Address=224.3.5.2, Port=35463, TTL=4}
[java]
[java] MasterMemberSet
[java] (
[java] ThisMember=Member(Id=1, Timestamp=2009-12-18 10:15:16.031, Address=10.187.80.135:8088, MachineId=57735, Location=sit
e:au.oracle.com,machine:papicell-au,process:3708, Role=CoherenceServer)
[java] OldestMember=Member(Id=1, Timestamp=2009-12-18 10:15:16.031, Address=10.187.80.135:8088, MachineId=57735, Location=s
ite:au.oracle.com,machine:papicell-au,process:3708, Role=CoherenceServer)
[java] ActualMemberSet=MemberSet(Size=1, BitSetCount=2
[java] Member(Id=1, Timestamp=2009-12-18 10:15:16.031, Address=10.187.80.135:8088, MachineId=57735, Location=site:au.orac
le.com,machine:papicell-au,process:3708, Role=CoherenceServer)
[java] )
[java] RecycleMillis=120000
[java] RecycleSet=MemberSet(Size=0, BitSetCount=0
[java] )
[java] )
[java]
[java] Services
[java] (
[java] TcpRing{TcpSocketAccepter{State=STATE_OPEN, ServerSocket=10.187.80.135:8088}, Connections=[]}
[java] ClusterService{Name=Cluster, State=(SERVICE_STARTED, STATE_JOINED), Id=0, Version=3.5, OldestMemberId=1}
[java] InvocationService{Name=Management, State=(SERVICE_STARTED), Id=1, Version=3.1, OldestMemberId=1}
[java] DistributedCache{Name=DistributedCache, State=(SERVICE_STARTED), LocalStorage=enabled, PartitionCount=257, BackupCou
nt=1, AssignedPartitions=257, BackupPartitions=0}
[java] ReplicatedCache{Name=ReplicatedCache, State=(SERVICE_STARTED), Id=3, Version=3.0, OldestMemberId=1}
[java] Optimistic{Name=OptimisticCache, State=(SERVICE_STARTED), Id=4, Version=3.0, OldestMemberId=1}
[java] InvocationService{Name=InvocationService, State=(SERVICE_STARTED), Id=5, Version=3.1, OldestMemberId=1}
[java] )
[java]

Few things to note here.

- We don't have anything in the SRC directory we simply add code we wish to use in our cache server here, like cahe store implementations etc.

- When you do have SRC to compile you will need to add a package task as shown below for example.

<target name="package"
depends="compile"
description="Package application into ${ant.project.name}.jar">
<jar basedir="${classes.dir}" destfile="${lib.dir}/${ant.project.name}.jar">
<include name="**/*.class"/>
</jar>
</target>

From the build.xml there is also a target to start a JMX enabled node using "ant run-jmx"

Wednesday, 9 December 2009

PLSQL commit every X records and Coherence putAll every X records

Note for self:

Was using this in Write-Behind Caching Demo with Oracle Coherence using PLSQL Bulk Binds.

When using PLSQL to bulk insert code as follows to control the commit time.

-- control number of records to insert before calling COMMIT
NUM_OF_RECORDS_TO_INSERT constant number := 10000;

IF (mod(l_count, NUM_OF_RECORDS_TO_INSERT) = 0) THEN
FORALL i IN mid.FIRST..mid.LAST
insert into messages (message_id, message_type, message)
values (mid(i), mt(i), m(i));
END IF;

When loading many cache records ensure we only call putAll to control the amount of records to insert into the cache in one hit.
final private static int BATCH_SIZE = 1000;

Map buffer = new HashMap();

long start = System.currentTimeMillis();

for (int i = 1; i <= records; i++)
{
Message message = new Message
(new BigDecimal(i),
"M",
String.format("Message %s from test client", i));
buffer.put(String.valueOf(i), message);

if ((i % BATCH_SIZE) == 0)
{
messageCache.putAll(buffer);
buffer.clear();
}
}

if (!buffer.isEmpty())
{
messageCache.putAll(buffer);
buffer.clear();
}

Friday, 4 December 2009

Having SQL*Plus run within Jdeveloper's Log window

Invoking SQL*Plus is what I do a lot from JDeveloper, so there are 2 things I setup everytime I do a fresh install of JDeveloper.

1. Use external tools to avoid having to enter password as per this blog entry a while ago.

http://theblasfrompas.blogspot.com/2007/10/avoiding-having-to-enter-password-when.html

2. Secondly I now only use sqlplus.exe rather then sqlplusw.exe to ensure that it never leaves JDeveloper itself and so the output is redirected to JDeveloper's log window. Of course you have to then add "exit" to your scripts so that the process itself doesn't hang around.

Also it's worth making sure you start from the directory of the SQL file your invoking if you wish to include other files as part of the SQL script itself which don't reference a path themselves.

Eg:

Program Executable: D:\oracle\product\10.2.0\db_1\BIN\sqlplus.exe
Arguments: scott/tiger@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=beast.au.oracle.com)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=linux11g))) @${file.path}
Run Directory: ${file.dir}

Demo output as follows showing how I invoke SQL*Plus and what we pass into it to avoid opening up a new window for SQL*Plus.