Category Archives: J2EE

Ant & Tomcat Manager on virtual hosts

I’m kicking out a couple freelance projects using Struts and Hibernate in the next couple weeks, this weekend I was fiddling with the Ant build script and I remembered Tomcat Manager App, which allows you to reload contexts while Tomcat is running (as well as start, stop, install etc..). Unfortunately, the /manager application only sees applications within the virtual host it’s running in and because I’m working with a couple different applications, I have multiple virtual hosts and I need to be able to utilize the /manager application from each one.

Turns out it’s not all that hard to get the /manager application working within a different virtual host… as long as you read the documentation very thoroughly. It’s as simple as adding this:

<Context path="/manager" debug="5" docBase="${CATALINA_BASE}\server\webapps\manager" privileged="true" />

(where ${CATALINA_BASE} is the absolute path to your tomcat install) to the virtual host element you have setup in server.xml (for those not experienced with Tomcat, adding a ‘context’ is similar to adding a virtual directory in IIS, make any more sense?). The one gotcha (in bold) is the privileged attribute. It *must* be set to true to run the /manager or /admin applications in virtual host besides localhost.

Reloading the application using Ant is a breeze, the Tomcat documenation includes an example build file, in short all you need is this:

<property name="path" value="/myapp"/>
<property name="url" value="http://localhost:8080/manager"/>
<property name="username" value="myusername"/>
<property name="password" value="mypassword"/>
<taskdef name="reload" classname="org.apache.catalina.ant.ReloadTask"/>
<target name="reload" >
<reload
  url="${url}"
  username="${username}" password="${password}"
  path="${path}"/>
</target>

Make sure that you have the catalina-ant.jar file coped from {Tomcat_install}\server\lib\ to your {Ant_install}\lib. If you are using Eclipse, go to Windows –> Preferences –> Ant –> –> Runtime –> Classpath and add catalina-ant.jar to the Runtime classpath.

ColdFusion & log4j

Integrating log4j and CFMX - An open source Java project gives developers new capabilities The January issue of ColdFusion Developer’s Journal features an article I wrote on how to integrate ColdFusion and log4j entitled “Integrating log4j and CFMX – An open source Java project gives developers new capabilities”. You can read it here.

While not especially interesting for developers writing simple ColdFusion applications, I’m finding that log files are becoming especially useful in applications with multiple tiers and clients. Even if you don’t use log4j and ColdFusion, I’d suggest taking a long look at your application to find out where it might be helpful to make your application more transparent.

QueryParser … in NLucene

Misleading title. I implemented the first of the examples that Erik Hatcher used in his
article about the Lucene QueryParser
, only I used NLucene. Lucene and NLucene are very similar, so if anything, it’s interesting only because it highlights a couple of the differences between C# and Java.

First, here’s the Java example taken directly from Erik’s article:

public static void search(File indexDir, String q) {
  Directory fsDir = FSDirectory.getDirectory(indexDir, false);
  IndexSearcher is = new IndexSearcher(fsDir);
  Query query = QueryParser.parse(q, "contents", new StandardAnalyzer());
  Hits hits = is.search(query);
  System.out.println("Found " hits.length() +
    " document(s) that matched query '" q "':");
  for (int i = 0; i
The NLucene version looks eerily similar:

public static void Search(DirectoryInfo indexDir, string q) {
  DotnetPark.NLucene.Store.Directory fsDir = FsDirectory.GetDirectory(indexDir, false);
  IndexSearcher searcher = new IndexSearcher(fsDir);
  Query query = QueryParser.Parse(q, "contents", new StandardAnalyzer());
  Hits hits = searcher.Search(query);
  Console.WriteLine("Found " + hits.Length +
    " document(s) that matched query '" + q + "':");
  for (int i = 0; i
The differences are mainly syntax.

First, Erik used the variable name 'is' for his IndexSearcher. In C# 'is' is a keyword, so I switched the variable name to 'searcher'. If you're really geeky, you might want to brush up on all the Java keywords and the C# keywords.

Second, while Java uses the File class to describe directories and files, the .NET Framework uses the DirectoryInfo class.

Third, Java programmers are encouraged to capitalize class names and use camel Case notation for method and variable names while C# programmers are encouraged to Pascal notation for methods and camel Case for variables, so I switched the static method name from 'search' to 'Search'.

Next, 'Directory' is a system class, so the reference to the NLucene directory needed to be fully qualified:

DotnetPark.NLucene.Store.Directory fsDir = FsDirectory.GetDirectory(indexDir, false);

rather than this:

Directory fsDir = FsDirectory.GetDirectory(indexDir, false);

Finally, the Hits class contains a couple differences. Java programmers use the length() method on a variety of classes, so it made sense for the Java version to use a length() method as well. C# introduced the idea of a property, which is nothing more than syntactic sweetness that allows the API developer to encapsulate the implementation of a variable, but allow access to it as if it were a public field. The end result is that instead of writing:

for (int i = 0; i
in Java, you'd use this in C#:

for (int i = 0; i
The authors of Lucene also decided to use the C# indexer functionality (which I wrote about a couple days ago) so that an instance of the Hits class can be accessed as if it were an array:

Document doc = hits[i].Document;

I put together a complete sample that you can download and compile yourself if you're interested in using NLucene. Download it here.

Fail-Safe Amazon Image… using Java, C# & ColdFusion

Paul of onfocus.com fame (and the fabulous SnapGallery tool) wrote an article for the O’Reilly Network recently that (I think) was an excerpt of his recently released book “Amazon Hacks“. Anyway, he shows how you can check to see if an image exists on amazon.com using ASP, Perl, and PHP and I thought it would be fun to show how to do the same thing in Java, C# and ColdFusion. His examples were all functions of the form:

Function hasImage(imageUrl)

so I’m following that style. In Java you’d end up with something like this:

public static boolean hasImage(String url) {
boolean result = false;
  try {
    URL iurl = new URL(url);
    HttpURLConnection uc = (HttpURLConnection)iurl.openConnection();
    uc.connect();
    if (uc.getContentType().equalsIgnoreCase("image/jpeg")) {
      result = true;
    }
    uc.disconnect();
  } catch (Exception e) {
  }
  return result;
}

In C#, almost the exact same thing:

public static Boolean HasImage(String url) {
  Boolean result = false;
  try {
    HttpWebRequest webreq = (HttpWebRequest)WebRequest.Create(url);
    WebResponse res = webreq.GetResponse();
    if (res.ContentType == "image/jpeg") {
      result = true;
    }
    response.Close();
  } catch {
  }
  return result;
}

and then in ColdFusion:

<cffunction name="hasImage" returntype="boolean" output="no">
  <cfargument name="imageUrl" type="string" required="yes">
  <cfhttp url="#imageURL#" method="GET">
  <cfif cfhttp.responseHeader["Content-Type"] EQ "image/jpeg">
    <cfreturn true>
  <cfelse>
    <cfreturn false>
  </cfif>
</cffunction>

The full source for all these examples are available:

· Amazon.java
· Amazon.cs
· amazon.cfm

Enjoy!

Creating RSS using Java

I wanted to create RSS feeds for karensrecipes.com using Java. I did my ‘research‘, came to this page: Ben Hammersley.com: Java RSS libraries and then used the RSS4j library to create a servlet that serves up dynamic RSS feeds of the 10 most recently created recipes per category (samples: Breakfast, Soup, Barbeque..).

They syntax is pretty simple, you get an RssDocument and set which version you want to use (RSS 1.0, .9 or .91):

RssDocument doc = new RssDocument();
doc.setVersion(RssDocument.VERSION_10);

and then create a RssChannel object and add that to the RssDocument:

RssChannel channel = new RssChannel();
channel.setChannelTitle("Karens Recipes | Most Recent");
channel.setChannelLink("http://www.karensrecipes.com/3/Soup/default.jsp");
channel.setChannelDescription("The 10 most recently added recipes in the soup category.");
channel.setChannelUri("http://www.karensrecipes.com/rss/?categoryid=3");
doc.addChannel(channel);

Next, you’ll retrieve the items using a database, the file system, etc… and add each item as a RssChannelItem:

// connect to the datasource
// iterate over something (db? vector?...)
RssChannelItem item = new RssChannelItem();
item.setItemTitle(label);
item.setItemLink(link);
item.setItemDescription(description);
channel.addItem(item);

and then finally, using the RssGenerator class, call the generateRss() method, in this case I’m sending the output to a Servlet PrintWriter:

PrintWriter out = response.getWriter();
RssGenerator.generateRss(doc, out);

You could just as easily write it to a file:

File file = new File("/opt/data/rss.xml");
try{
RssGenerator.generateRss(doc, file);
System.out.println("RSS file written.");
}
catch(RssGenerationException e){
e.printStackTrace();
}

Simple. Easy to use.

re: CFMX Java-jock jihad

Geoff makes a couple blanket statements in his post about how the Java world doesn’t understand CFMX. I don’t agree with a couple of them:

· ColdFusion remains the only answer to making Java accessible to a mass of non comp-sci web developers — I don’t have a computer science degree, neither do 3 of the other 4 developers at Mindseye (all of whom have written Java applications and all of who have spoken at DevCon) and I’ve created a couple sites using Java & JSP technology so to say that non comp-sci web developers can’t understand Java is patently incorrect. I think it also bears mentioning that Java is considered by some to be a language for the masses:

The advantages of Java is that it easily serves as a lingua franca – everyone can read a Java program and understand what is going on…“,

· …most Java developers fail to see where CFMX fits into their world of programming… — Why should they care? There are a number of other scripting languages that work with Java, PHP being one of them. Java developers have enough to worry about… they’re too busy choosing between web frameworks (struts, tapestry, webwork2), persistence models (obj, castor, jdo..) and templating mechanisms (velocity, cocoon..). It’s commonly mentioned/demonstrated that ColdFusion is easy by showing how few lines it takes to query a database, but has anyone ever asked an enterprise Java developer how many queries they put into a JSP? .

With that said, I think that Geoff has the right attitude, starting a “.. post-positive campaign highlighting CFMX/Java symbiosis” is a great starting point. Go one step further though. Build a J2EE application, learn Struts, use OJB. Geoff claims that J2EE people don’t understand CFMX. How well do CFMX people understand J2EE?