28 September 2007

Using JAXB 2.0 with OC4J 10.1.3.x

OC4J 10.1.3.x provides a JAXB 1.0 implementation as part of its standard runtime. If you want to use JAXB 2.x then its easy to do using the shared-library mechanism of OC4J.

As a simple test of the JAXB 2.0 capabilities, a simple application can be used that makes use of the JAXB 2.0 features. In the example used herein, the application is a simple Web application that makes use of two POJOs that are annotated with JAXB 2.0 annotations.

Build a Test Application:
package sab.demo.jaxb.model;

import java.util.ArrayList;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.*;

/**
*
@author sbutton
*
*/
@XmlType(propOrder = { "manufacturer", "model", "year",
"color"
, "registration", "owners" })
@XmlRootElement(name = "vehicle")
@XmlAccessorType(XmlAccessType.PROPERTY)
public class Vehicle {
long id;
String registration;
String manufacturer;
String model;
String year;
String color;
ArrayList<Owner> owners = new ArrayList<Owner>();

public Vehicle() {
// TODO Auto-generated constructor stub
}

...
...
}

Instances of the POJOS are then created from a JSP page, where they are marshalled into an XML document and then displayed by the JSP:
<%
try {
JAXBContext context = JAXBContext.newInstance(Vehicle.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);

Vehicle xtrail = new Vehicle(1L, "Nissan", "X-Trail",
"2002"
, "Silver", "ABC-123");
xtrail.addOwner(new Owner(1L, "Fred", "Bloggs"));

Vehicle golf = new Vehicle(2L, "Volkswagen", "Golf",
"2002"
, "Silver", "XYZ-123");
golf.addOwner(new Owner(1L, "Fred", "Bloggs"));
golf.addOwner(new Owner(2L, "Freda", "Bloggs"));

StringWriter sw = new StringWriter();
marshaller.marshal(xtrail,sw);
out.println(escapeHtml(sw.toString()));

sw = new StringWriter();
marshaller.marshal(golf,sw);
out.println(escapeHtml(sw.toString()));

} catch (JAXBException e) {
e.printStackTrace(new PrintWriter(out));
}
%>
The application is then packaged up into a WAR and an EAR file ready for deployment.

Prepare the Server: Using ASC, publish a shared-library that contains the JAXB 2.0 JAR files.



Deploy the Application: When deploying the application, use the Classloading Task and import the "jaxb 2.0" shared-library so the application has access to the JAXB 2.0 implementation.



When the application is run, the Vehicle and Owner instances are marshalled to XML and displayed in the JSP page.



Voila.

20 September 2007

Command Line Monitoring of Thread Pool Sizes

Want to periodically view the OC4J thread pool sizes from the command line?

Using Groovy + JMX , its dead simple:
import demo.oc4j.jmx.*;
import java.text.*;

def period = 5000L
def client = new OC4JClient()
def df = DateFormat.getTimeInstance(DateFormat.LONG)

try {
client.connect("service:jmx:rmi://10.187.112.178:23791",
"oc4jadmin", "welcome1")

println "$client\n"

http = client.helper.createGroovyMBean(
"oc4j:j2eeType=ThreadPool,name=http,J2EEServer=standalone")

system = client.helper.createGroovyMBean(
"oc4j:j2eeType=ThreadPool,name=system,J2EEServer=standalone")
jca=client.helper.createGroovyMBean(
"oc4j:j2eeType=ThreadPool,name=jca,J2EEServer=standalone")


while(true) {
now = df.format(new Date(System.currentTimeMillis()));
println "$now HTTP:[$http.poolSize] JCA:[$jca.poolSize] System:[$system.poolSize]"
Thread.sleep(period)
}
} finally {
println 'Closing'
client.close()
}

This makes use of the OC4J helper library, which you can access here.

A simple script to run this would look like this:

@setlocal
set J2EE_HOME=d:\java\oc4j-10133-prod\j2ee\home
set GROOVY_HOME=d:\java\groovy-1.0
set classpath=lib\oc4jgroovy.jar;%GROOVY_HOME%\lib\commons-cli-1.0.jar;/
%GROOVY_HOME%\embeddable\groovy-all-1.0.jar;%J2EE_HOME%\admin_client.jar;%J2EE_HOME%\oc4jclient.jar

java -classpath %CLASSPATH% groovy.lang.GroovyShell src\threadlevel.groovy
@endlocal


When the script is run, it produces this sort of output:

Client is connected to: rmi://10.187.112.178:23791 oc4jadmin [connectionCaching:
true, httpTunneling:false, locale:not set]

1:03:54 HTTP:[7] JCA:[1] System:[7]
1:03:59 HTTP:[7] JCA:[1] System:[7]
1:04:06 HTTP:[7] JCA:[1] System:[7]
1:04:11 HTTP:[7] JCA:[1] System:[7]


----------------
Listening to: Ned's Atomic Dustbin - What Gives My Son?

13 September 2007

Remote copy with SCP and JDeveloper External Tools

I'm currently working on developing some examples for use cases for our Release 11 product. I tend to flick around between the IDEs I use, Eclipse and JDeveloper -- for example, I find that the support JDeveloper has for packaging J2EE applications is a bit easier to use than the analogs in Eclipse. Or perhaps its just that I've used it a bit more and know how to work around its foibles.

Anyway, the situation I ran into is that my install of 11AS is on a hosted server back at HQ. And I'm using JDeveloper 10.1.3 on my laptop here in Adelaide. So any time I wanted to deploy the applications to test them, I had to manually SCP/SFTP the application archive up to the server then deploy it. I know its trivial, but it was becoming a pain in the arse after a while. It's kind of funny how something so incidental sometimes becomes a beast of burden.

How could I make my life easier? Well I was just about to write myself a 5 line Ant script to do it, which used the task and then run that from JDeveloper to automate the copy process. But then I just happened to notice the "External Tools" menu item.
Hmm I said out loud -- could I just use that instead?

Well all you need to do is crack open the External Tools menu item and Add a new item.

To copy a file from my local PC to the server, I ultimately need a command that looks like this :

pscp -pw password username@server:/dir

All you need to do then is to fill in the relevant fields to produce that command.

There are some nice elements in the dialog that help you construct the generic command. I used three of these in my command:
  1. To allow me to enter the password when the command is run, I used the prompt directive:

    ${prompt:label=Password}

  2. To specify the file to upload, I used the file.path directive:

    ${file.path}

  3. To specify the target server, I used an environment variable substitution. I'm lazy and to avoid typing, I set the common target server details as an environment variable so that from the command line I can use some shorthand like this "pscp %SCP% ...". To include the environment variable, I used the env.var directive:

    ${env:var=SCP}
In the external tool dialog, putting it together looks like this:



Cool.

Now to put it to use.

When I want to copy an application archive up to my server for deployment, all I need to do is select the archive in the Navigator and select PSCP from the right mouse menu:



The password is then queried:



And finally the full command is constructed and run:



Voila.

One gotcha I found was that the deployment archives are not shown by default in the various JDeveloper Navigators (why it doesn't show them in a "deploy" directory in the navigator BTSOOM).

So to force JDeveloper to show you the generated archives, add the "deploy" directory to the Project Content directories:



----------------
Listening to: Ride - Twisterella

10 September 2007

Using Shared Libraries to configure Log4j

As I was mucking around with Log4j last week, it occurred to me that I could make use of the OC4J shared-library mechanism to inject the Log4J properties files into an an application when it was being deployed -- after all the properties file is just read from the classpath.

Even better, what this enables an administrator to do is to configure a set of shared-libraries that contain different log4j properties file, say enabling different log levels, and then choose between them when the application is deployed. Or additionally, make changes to in a post-deployment manner to switch between different logging settings.

OK, enough with the banal description, here's a few screen shots to show you what I'm dribbling on about here.

First off, lets assume you have a desire to capture and route your log4j entries into the OC4J log system using the OracleAppender as described here and you have a properties file that configures the appropriate settings and the log level you want to enable.

log4j.rootLogger=INFO,OJDL
log4j.appender.OJDL=oracle.core.ojdl.log4j.OracleAppender
log4j.appender.OJDL.LogDirectory=${oracle.j2ee.home}/log/oc4j
#log4j.appender.APP1.MaxSize=1000000
#log4j.appender.APP1.MaxSegmentSize=200000
#log4j.appender.APP1.Encoding=iso-8859-1
log4j.appender.OJDL.ComponentId=OracleProd

The first thing to do is to put the log4j.properties file into a JAR file, then deploy it as a shared-library to OC4J.





Once the shared-library has been published, you will see it available on the server shared-libraries page, ready to be imported. Note that in the below, I actually have two different log4j.config shared-libraries deployed.



Once the shared-library is deployed, it is then available to be imported by applications when they are deployed. By importing the log4j.info.config shared-library, the log4j.properties file is made accessible to the application and therefore used to to configure log4j for the application.

To import the shared-library during the deployment process, use the Configure Classloading button on the Deployment Tasks page.





By selecting the desired log4j.config shared-library, it will be made available to the application, and therefore dictate how the log4j log entries for the application are handled. In this specific case, the ROOT logger is set to the INFO level, and the OracleAppender is being employed to direct the log entries into the OC4J log system.

Ultimately the customized shared-library settings for the application are written into the orion-application.xml for the deployed application.



If at some point you wanted to change this application to use a lower log level such as DEBUG or TRACE then you can easily modify the import-shared-library statement to import the shared-library that has the relevant log4j.properties configuration file.

In summary, using the Oc4J shared-library mechanism and a consistent naming convention should enable you to have as many reusable log4j configurations as you need that can be applied to your applications.

----------------
Listening to: Billy Bragg - A New England

06 September 2007

Directing Log4j logs into OC4J logging system

My last posts have focussed on using the JDK standard logging API, and directing the logs being emitted into the OC4J logging system so they can be viewed and searched using the ASC LogViewer.

The log-handler mechanism we have works with the JDK standard logging constructs. The appender mechanism used by log4j is not covered by the basic configuration option in j2ee-config.xml.

However if you are using log4j, then on the surface it looks you are apparently SOL.

But if you want to get a little dirty, here's how you can also choose to redirect log4j logs into the OC4J log files.

In the OracleAS distribution, we ship a JAR file -- $ORACLE_HOME/diagnostics/lib/ojdl-log4j.jar -- that contains an OracleAppender class. Turns out, this class is a log4j appender that transforms log4j messages into the OJDL XML form.

To use this appender, simply configure it using your preferred log4j configuration mechanism. I'll use log4j.properties as an example:

log4j.rootLogger=TRACE,OJDL
log4j.appender.OJDL=oracle.core.ojdl.log4j.OracleAppender
log4j.appender.OJDL.LogDirectory=${oracle.j2ee.home}/log/oc4j
#log4j.appender.APP1.MaxSize=1000000
#log4j.appender.APP1.MaxSegmentSize=200000
#log4j.appender.APP1.Encoding=iso-8859-1
log4j.appender.OJDL.ComponentId=OracleProd

In this configuration, the log4j messages will be directed into the $ORACLE_HOME/j2ee/home/log/oc4j/log.xml file -- which is the "Diagnostics" file read and displayed by LogViewer.

To make use of the OracleAppender, you have to ensure that you have the classes available to the application to use.

One approach it to include the libraries within the application itself -- with JEE5 applications, this is dead simple using the new <librar-directory> facility, with which you specify a directory within the EAR file to hold libaries, and then plunk the libraries into that directory. EasyPeasy!

Another approach to this is to create a shared-library containing the log4j library and the ojdl-log4j.library, and then import this into the application when it is being deployed so the libraries are available to the application.

If you have a Web application, just plunk the libraries into the WEB-INF/lib directory and go.

Something to keep in mind when you are using the ojdl-log4j library is that it has a dependency on the log4j library, so they have to both be accessible at the same classloader level.

Once you have it configured, then the one log.xml file will contain log entries from OC4J, as well as any logs from log4j.

----------------
Listening to:
Powderfinger - Love your way

05 September 2007

Capturing and viewing application log messages with LogViewer

Or put another way ... directing application log messages into the OC4J logging system and viewing them.

Lets say you are wisely using some form of logging framework within your application. And when using OC4J, you use the LogViewer functionality within Application Server Control (ASC) to view the various log messages emitted by the susbsystems of OC4J. Perhaps, you think to yourself, I'd be quite convenient to also include the log messages from my application into the general OC4J log so it can be viewed from the same LogViewer.

Here's how it can be done!

I'm not getting in the religious argument as to which logging framework you are using. For pure expediency, my example will use the JDK logging API.

OK, so in your application, you are using a logger naming hierachy of some form, and using the logger to issue log messages at different levels.
Logger logger = Logger.get("foo.bar.web.EmployeeFrontEnd");

public
void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {response.setContentType(CONTENT_TYPE);
logger.fine(
String.format("Handling web request for %s", request.getRequestURL()));

PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head><title>EmployeeFrontEnd</title></head>");
out.println("<body>");
Employee test = Employee.getTestInstance();
logger.finest(
String.format("Test Employee Instance: %s", test));
logger.finest(
String.format("Calling %s to locate office for %s",
employeeManager.toString(),
test.identifier(test.ID_SHORT)));
String location = employeeManager.locateEmployeeOffice(test);

logger.finest(
String.format("bean returned %s for %s ",
location, test.identifier(test.ID_SHORT)));
out.printf("<p>Employee: %s</br>Office: %s</p>", test.identifier(test.ID_SHORT), location);
logger.fine(String.format("Employee currently earns $%s", test.getSalary()));
test.raiseSalary(15D);
out.printf("<p>Give employee 15percent raise, now earns %s", test.getSalary());
out.println("</body></html>");
out.close();
}

Cool.

Now if you are using standard JDK logging, you can configure the logging handlers and log levels using various mechanism, to ultimately direct the log entries from the application into some form of persistent form to view at a later point.

Now this is where the intersection with the standard logging API, OC4J and the ASC LogViewer intersect.

First off, the ASC LogViewer knows about all the log files that are generated by OC4J. Among them is the big daddy of log files -- j2ee/home/log/oc4j/log.xml -- this is known as the diagnostics log file.

How this file is constructed as a log target is done in the j2ee/home/config/j2ee-config.xml file, where the oc4j-handler is configured to use the Oracle common logging mechanism:

<log_handler name="oc4j-handler" class="oracle.core.ojdl.logging.ODLHandlerFactory">
<property name="path" value="../log/oc4j"/>
<property name="maxFileSize" value="10485760"/>
<property name="maxLogSize" value="104857600"/>
<property name="encoding" value="UTF-8"/>
<property name="supplementalAttributes" value="J2EE_APP.name,J2EE_MODULE.name,WEBSERVICE.name,WEBSERVICE_PORT.name"/>
</log_handler>

Then by convention,, the oracle naming hierachy is specified as being handled by this oc4j-handler:

<logger name="oracle" level="NOTIFICATION:1" useParentHandlers="false">
<handler name="oc4j-handler"/>
<handler name="console-handler"/>
</logger>
Thus any messages written into the "oracle" root logger will be directed to the oc4j-handler, which writes them out in XML form to the j2ee/home/log/oc4j.log.xml file.

To therefore include log messages from your application in the OC4J diagnostics log file, all you need to do is to add a new <logger> entry in the j2ee-config.xml file that specifies your logger name and the level, and declares it to use the oc4j-handler.

<logger name="foo" level="FINEST">
<handler name="oc4j-handler"/>
</logger>

Now using ASC, select the logs entry at the bottom of the page to view all the logs.



By clicking on the the Diagnostics Logs file, you should see it showing both log entries for OC4J PLUS the log entries from your application.



You can see from the log messages the component where the log entry was generated. From the example above you can see log messages from the web_EmployeeFrontEnd component and the ejb_EmployeeManagerBean.

Now the really really cool thing you can do from here is to view all the log entries from the same execution path. Basically what happens is that the Oracle common logging mechanism allocates an execution context ID to every log message, which enables it to then correlate the various log entries from the different components of an execution path. By simply clicking on the Execution Context ID (ECID) link for a log entry of interest, all the log files will be searched for that ECID and each entry will then be displayed in time stamp order.

This effectively gives you the log entries, in sequence for an individual request.



How's that for a handy capability!

Once your log entries are being handled within the Oracle common logging mechanism, you can then utilize the search facilities within the LogViewer to search for items of interest. Explore away!

And for one final rabbit out of the hat for this blog entry, you can also use ASC to configure your application level loggers. On the Administration page, select the Configure Loggers link. If you application has run and your loggers have registered themselves (or you statically configured them in the j2ee-config.xml file) you will see the logger name listed, along with a select list to allow you to specify the levels for each logger. This lets you configure your custom application logging on the fly.



----------------
Listening to: Pixies - Here Comes Your Man

03 September 2007

Getting @ an EJBContext from External Interceptors

If you need to get at the EJBContext of the target bean from an external interceptor class, then one easy way to do it with OC4J is to lookup the following resource from within the interceptor:

EJBContext context = (EJBContext)new InitialContext().lookup("java:comp/EJBContext");

In OC4J 11 even this marginal piece of code won't be necessary as the EJBContext (and any other type of resource) can be injected directly into the interceptor.

Before I was made aware of the simpler solution above, I was resorting to using some reflection code to try and work out if there was an applicable way to get the EJBContext from the target bean. It uses first a direct field check and if that yields no results, it then looks for an accessible method that has returns an EJBContext class, or a derivative thereof.

// The EJBContext classes
final List contextClasses = Arrays.asList(
new Class[] {
javax.ejb.EJBContext.class,
javax.ejb.SessionContext.class });
/**
* Try and get the principal name from the target bean class
* @param target
* @return name of the principal
* @throws Exception
*/
String getPrincipalName(Object target) throws Exception {
String ret = getPrincipalNameFromField(target);
if(ret != null) {
return ret;
} else {
ret = getPrincipalNameFromMethod(target);
}
return(ret != null ? ret : "Ghost Rider");
}

private String getPrincipalNameFromField(Object target) throws Exception {
for(Field field : target.getClass().getFields()) {
if(contextClasses.contains(field.getType())) {
EJBContext ctx = (EJBContext)field.get(target);
return ctx.getCallerPrincipal().getName();
}
}
return null;
}

private String getPrincipalNameFromMethod(Object target) throws Exception {
Method[] methods = target.getClass().getMethods();
for (Method method: methods) {
if(contextClasses.contains(method.getReturnType())) {
EJBContext ret = (EJBContext)method.invoke(target, null);
return ret.getCallerPrincipal().getName();
}
}
return null;
}


This worked pretty well in my tests, but of course it needs the target bean class to be in a cooperative form -- the EJBontext either needs to be accessible as a public field, or there needs to be a public method to get the object from the target bean.

The JNDI lookup is easier and more reliable.

My Turner Flux

It's distinctly not OC4J or Java related, but I'm so rapt with this that I just had to express it somewhere.

My long awaited Turner Flux MTB frame has finally arrived, after close to 6 months of waiting.



I've been gathering all the parts to put on it over the last few months, so its just about ready to get built up -- I've got a sweet collection of bits for it -- Avid Juicy Carbon brakes, Race Face Deus crankset, SRAM X.0 running gear, Mavic Crossmax wheel set, Thomson seatpost and stem and more. I've just found somewhere to pick up Fox F100 RLC fork which completes the bill.

I should be living in mortal fear of my wife looking closely at the credit card bills ... but she's a total champ about it all. I think she likes getting me out of the house or maybe its because I'm a much happier bloke after a ride.

Once the build it done, I may never find the time to post another blog entry

Stop that cheering ok! :-)

Upate Sept 11: all the bits and pieces are now in place and I dropped the frame and bits into Bio-Mechanics Cycles to get it built up. Prodigy Pete seems like a top bloke, who comes very highly recommended. I think the only thing I forgot to pick up was a set of handlebar grips. Luckily Pete had some on hand. I kind of forgot to get a saddle too, so I've scavenged the Fizik Aliante off of my roadie for the time being and will see how that works out. I then may either source a Gobi, or leave the Aliante on the Turner and get my Arione back from my mate to use on the roadie.

Update Sept 20: Here's my Flux fully assembled.

It's been out for a few rides already.

Having never spent any significant time on other dual suspension rides, I can't compare it to anything else. However just in its own right, the bike is utterly fantastic. Even on the first ever ride around the block, it felt immediately comfortable. You feel like you are one with the bike and in total control.

Taking it out on the trails, the most noticeable aspect is simply how it rides. Just point and go and the bike will take you wherever you want. It floats over rocks, roots, ruts as if they weren't there. It feels like it powers through corners with the amazing amount of traction you get from the active rear end. Landing from small jumps is barely even noticeable, which lets you keep a line much more easily.

The other thing that became really apparent after a few rides was that my lower back wasn't sore at all -- riding the hardtail and bouncing around all over the shop, after an hour or so my back usually tightens up. But on this, I just didn't feel a thing.

So far, it's been a totally positive experience and I can't wait to spend some more time on it.






----------------
Listening to:
John Butler Trio - Funky Tonight

Accessing Return Values from EJB Interceptors

Continuing from my last posting regarding the application of EJB3 interceptors to existing applications, there's another interesting tidbit regarding how to access the return value of an EJB method call in an interceptor.

Thanks to some sage advice from members of our EJB team (who have authored a simply outstanding book in my opinion) turns out that you can use a simple pattern like this in your interceptor method:

public Object intercept(InvocationContext ctx) throws Exception {

// do stuff as pre-invoke
...

// Execute the bean method, or next interceptor in the chain
Object result = ctx.proceed();


// do stuff as post-invoke
...

// return the result from the handler
return result;
}


Using this pattern, you have access to the pre and post invoke states of the method call on the bean.