Sunday, July 22, 2007

HTTP POST

Have you ever wanted to create/access a web service, but found solutions like SOAP just too slow? We ran into this problem at work not too long ago. With some help, I had created a web service accessible via SOAP. However, when we deployed and ran it in production for a couple of weeks, we were not satisfied with the speed and memory performance of the entire process. Since the service was (potentially) a high volume call, we determined that the overhead of using SOAP was a big hang up. The wrapping and unwrapping of the SOAP envelope for each call was really bogging down the server's processor. Another solution was needed.

We caught a break in that the service was strictly an internal call, therefore conforming to some silly (kidding!) standard to support external customers was not needed. We turned to something pretty basic, a bare-bones HTTP POST. The service would accept incoming XML, perform it's function and output XML as a response.

What we need: a Java servlet. Yep, that's it, just have the servlet respond via POST and you can rig it to capture incoming XML and pass it along to your business logic to do the dirty work.


public class PostServlet extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
BufferedReader in = null;
PrintWriter out = null;

try {
in = request.getReader();
out = response.getWriter();

// Set the response content-type
response.setContentType("text/plain");

// Read the incoming data from the request
String line = null;
StringBuffer inData = new StringBuffer();
while ((line = in.readLine()) != null) {
inData.append(line + "\n");
}

// Send the email message
BusinessLogicObject bc = new BusinessLogicObject();
String returnValue = bc.executeBusinessLogic(inData.toString());

// Write the return value to the response
out.print(returnValue);
}
catch (Throwable e) {
out.close();
in.close();
e.printStackTrace();
}
}
}
To test the servlet, we can create a simple JSP page:
<%@ page language = "java"
import = "java.text.*, java.util.*, java.io.*, java.net.*, java.sql.*"
%>
<%
String submitted = request.getParameter("submitted");
String templateId = "";
String xmlDoc = "";
String servletResponse = "";
if ("1".equals(submitted)) {
// Process the form and send the emailer message
templateId = request.getParameter("templateId");
xmlDoc = request.getParameter("xmlDoc");

// Compose the HTTP POST
PropertyManager.load("/emailer");
String emailerWebServiceHost = PropertyManager.getProperty("web_service_host");
String urlString = "http://" + emailerWebServiceHost + "/servlets/PostServlet";
URL url = new URL(urlString);
HttpURLConnection con = (HttpURLConnection)url.openConnection();
con.setAllowUserInteraction(true);
con.setDoInput(true);
con.setDoOutput(true);
con.setUseCaches(true);
con.setFollowRedirects(false);
con.setRequestMethod("POST");
con.connect();

// Set the request info (XML)
PrintWriter output = new PrintWriter(new OutputStreamWriter(con.getOutputStream()));
output.print(xmlDoc);
output.flush();
output.close();

// Get the response (String)
BufferedReader input = new BufferedReader(new InputStreamReader(con.getInputStream()));
String line = null;
StringBuffer inputData = new StringBuffer();
while ((line = input.readLine()) != null) {
inputData.append(line + "\n");
}
servletResponse = inputData.toString();
}
%>
<html>
<head>
<title>Send Email Servlet Test Page</title>
</head>

<body>
<p><b>Send Email Servlet Test Page</b></p>

<form action="servletTest.jsp" method="post">
<table border="0" align="center">
<tr>
<td>Select the template ID to use:</td>
</tr><tr>
<td>
<select name="templateId">
<option value="XMLType1">XMLType1</option>
<option value="XMLType2">XMLType2</option>
<option value="XMLType3">XMLType3</option>
<option value="XMLType4">XMLType4</option>
</select>
</td>
</tr><tr>
<td> </td>
</tr><tr>
<td>Specify the XML file to use:</td>
</tr><tr>
<td><textarea name="xmlDoc" cols="100" rows="20"></textarea></td>
</tr><tr>
<td align="center">
<input type="submit" name="submitButton" value="Submit" />
<input type="reset" name="resetButton" value="Reset" />
<input type="hidden" name="submitted" value="1" />
</td>
</tr>
</table>
</form>

<hr />

<table border="0" align="left">
<tr>
<td colspan="2"><b>Output</b></td>
</tr><tr>
<td>Template ID:</td>
<td><%= templateId %></td>
</tr>
</table>

<br clear="all" />
<br clear="all" />

<p>Servlet Output</p>
<pre>
<%= servletResponse %>
</pre>
</body>
</html>
Boom, done, that's all she wrote. Until next time.

Monday, July 16, 2007

Organization

So here I am, I'd rather be sleeping, but my body doesn't seem to want to agree with me. I thought I'd give some writing to calm my mind down and hopefully be off in la-la land soon.

Lately, I've been trying to re-organize and tidy up my apartment in the hopes of giving it less of that bachelor-pad feel. I've made small progresses here and there, but I'm realizing just how much stuff I have. I started by emptying out my office (mostly) into my living room and just one look tells me that I'm a) going to have to get rid of the junk I don't need anymore and b) get a lot more storage bits to keep myself sane. My main need is more shelving/bookcases, so it looks like a trip to Target, Bed Bath & Beyond, Staples and the like is in the works. In the meantime, my office is mostly empty while my living and bed rooms are complete disasters... what have I gotten myself into?

Sunday, June 17, 2007

Compy issues

The last few weeks have been pretty rough from a computer stand point. A little while back my computer just died, I tried a restart and got nothing, no POST beep or beep error codes. Nothing. Awesome. A little diagnosis later and I determine that the motherboard had died. Joy. In an age of rapidly progressing hardware, this pretty much meant I had to replace the "holy trinity" of computer parts: motherboard, CPU and RAM. Just to pile onto the fun, my perfectly good video card had to be replaced as well, since the AGP slot is basically extinct. A quick trip to newegg.com and a couple days of going stir-crazy, my computer is rebuilt.

I sit down in my chair, fire up the compy and... Windows won't start. @!#$ Not in safe mode, not in any mode. In all honesty, that's not a huge surprise considering I just replace most of the innards. I try to repair the installation, nada. *sigh* I break out my XP disks and resign myself to doing a complete reinstall... time passes... Finally, XP is installed, I go to activate it... "you have exceeded the number of times you can activate XP using this key"... grr... So I call customer support, go through their convoluted process to get my version of XP activated and finally have a fully function computer again. (Side note: I wonder what's going to happen when support for XP officially ends? Am I going to be able to activate my legit copy of Windows when I need to?)

Suffice to say, I'm mostly back up and running normally. I'm in the processes of getting everything "lived in" again In the meantime, I'm a bit stuck in neutral.

Friday, May 18, 2007

Samba (cont.)

As I said in my previous post, I finally got around to getting a Samba domain server up and running in my little home office. This post will be a brief rundown of how I managed to get a Samba server up and running. After all kinds of reading and getting to know Google quite well, it turned out to be quite a bit easier to set up than I originally anticipated. Some links that came in handy:

SAMBA (Domain Controller) Server For Small Workgroups With Ubuntu 5.10
SettingUpSambaPDC
Lightweight Gnome

Machine:
Athlon 1GHz
32MB RAM (going to upgrade this soon)
4 GB HDD (holds the OS, mounted as /)
80 GB HDD (to setup as a share, mounted as /share)

Step 1: Install Ubuntu
I went with the server install just to avoid all the extra stuff that normally comes with the default desktop install. I needed to save space since I was going to squeeze the entire OS onto a 4 GB hard drive.

Step 2: Install Gnome
Using the link above as a guide, I installed as minimal a Gnome desktop as I could. I like Linux, but I'm not that hardcore to want to work from a text interface. One little problem I had after I got Gnome up and going was that I was stuck in a 1024x768 screen resolution, despite picking other larger resolutions in the configuration. A solution I found was to re-run the setup program.

sudo dpkg-reconfigure xserver-xorg
After choosing all the defaults, I had to choose the "Medium" monitor detection instead of the default selection (Automatic I believe). Blessed again with a 1200x1024 resolutions, I was ready to move on to the next step.

Step 3: Installing/Configure Samba
With Gnome up and going and the Ubuntu package manager up and going, I simply fired up Synaptic Package Manager (System > Administration > Synaptic Package Manager) and installed samba and it's dependencies.

With Samba installed I used the information on the links above as a guide to setup my Samba configuration.
# Samba configuration file (/etc/samba/smb.conf)
[global]
workgroup = CEREBRO
server string = Samba %v on %L
netbios name = professorx
wins support = yes
dns proxy = no

log file = /var/log/samba/log.%m
log level = 1
max log size = 1000
syslog = 0

admin users = root
security = user
username map = /etc/samba/smbusers
guest account = nobody
encrypt passwords = yes
passdb backend = tdbsam
obey pam restrictions = yes
invalid users =
unix password sync = yes
passwd program = /usr/bin/passwd %u
passwd chat = *Enter\snew\sUNIX\spassword:* %n\n *Retype\snew\sUNIX\spassword:* %n\n *password\supdated\ssuccessfully* .
map to guest = Bad Password
password level = 0

add user script = /usr/sbin/useradd -m '%u' -g smbusers -G smbusers
delete user script = /usr/sbin/userdel -r '%u'
add group script = /usr/sbin/groupadd '%g'
delete group script = /usr/sbin/groupdel '%g'
add user to group script = /usr/sbin/usermod -G '%g' '%u'
add machine script = /usr/sbin/useradd -s /bin/false -d /var/lib/nobody %u

logon path =
logon home =
logon drive = H:

domain logons = yes
os level = 65
domain master = yes
preferred master = yes
local master = yes
logon script =

printcap = cups
printers = cups
load printers = yes

socket options = TCP_NODELAY
time server = no

[share]
path = /share
comment = Network Share
volume = Network_Share
writeable = yes
The links above spell out more of the Samba installation/configuration which can be followed with no additional information coming from me (though in the future I may come back and flush these steps out some more).

Step 4: Add machine to the domain
The machine I wanted to add to the domain is my Windows XP machine. This is done fairly easily by:

right click My Computer > Properties > Computer Name tab > Change

Choose the Domain radio button and specify the domain name. A dialog box should pop up, specify the Administrator username/password and you should get added to the domain. Restart the machine and boom, you are now part of the domain.

Tuesday, May 15, 2007

Samba... not the dance

Well after a lot of reading and procrastination I finally got a Ubuntu server running Samba set up as a domain controller. I'm still tweaking on the config file a bit, I will post it as soon as I get it finalized. Overall the process went pretty smoothly, but it did take me a couple of attempts. My first try I think I managed to jack things up pretty badly trying to get SWAT to run (web gui interface to the Samba config file). So I just cut bait and re-installed everything.

One quick note on the Ubuntu server, by default it runs in text mode after installation, but I still wanted some kind of gui interface. I managed to find a how-to (link to come) that walks through how to install a minimal Gnome interface.

Sunday, April 22, 2007

Vista broke my website...

... so it appears. One of our websites at work doesn't appear to work with this new fangled Windows Vista. Lately we've been getting complains of the site not working properly, customers would log in, click through a page or two and then boom, back to the login page. From where I sit, the site is acting line the Session is being invalidated. It appears that everyone experiencing the problem is running Vista and IE7. I've tested it on IE6, IE7 and Firefox on XP and the site works just fine, so last variable appears to be Vista. At the moment, we do not have a Vista box (we've also been told not to install IE7 yet), but there is one on the way. Hopefully there's a setting somewhere in their new security "features" that will get the site working again.

Sunday, April 8, 2007

That Tinkering Feeling

A friend of mine recently bought a new Mac desktop machine, his first such venture into the arena. I got to play around with it over the weekend and came away impressed. The neatest thing I got to see was the Parallels Desktop, a virtualization solution in which he setup Windows XP and was working on getting Ubuntu up and going.

While I don't see myself buying a Mac anytime soon, it did get me thinking about my little home network. I am strongly thinking about creating a new domain/file server based on Ubuntu and Samba, but first I'm going to need more hard drive space. And then, of course, I'll have to follow through. Updates to come... hopefully...

Wednesday, April 4, 2007

XSL Transformers: More Than Meets The Eye

I don't know how your workplace functions but mine has one glaring flaw, a lack of centralization. Take a look around and you can see a few places in which common tasks are being preformed across multiple teams. With the hope of starting a trend, work presented us with a fun little problem to solve. How can we centralize our outgoing e-mail messages? We have a handful of websites, some in .NET others in Java, each responsible for composing and sending their own e-mails (mostly confirmations and reminders).

To meet the centralization requirement we decided on setting up a web service that was then exposed to all development teams. Ok, one problem solved, but we still had to figure out how compose our data-centric e-mails and then send them out the door. Enter XSLT, in a nutshell what XSLT allows us to do is transform an XML document into some other format, in our case HTML and/or text. This will allow our web service to take an incoming XML document and transform it into an HTML page. In order to do these transformations programatically we will use the Xalan XSLT processor. Before we get started with the Java code, we will also need some XML and an XSLT template.

First the XML:


emailMessage.xml
----------------
<EmailMessage>
<Customer>
<customerFirstName>Joe</customerFirstName>
<customerLastName>Customer</customerLastName>
<customerEmail>joe.customer@somewhere.com</customerEmail>
</Customer>
<Service>
<confirmationNumber>12345-67</confirmationNumber>
<price>59.99</price>
<date>2007-04-04</date>
</Service>
</EmailMessage>


Now the XSLT:

emailMessage_html.xslt
----------------------
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/EmailMessage">
<html>
<head>
<title>Email Message Sample</title>
</head>
<body>
<div>
<p>Thank you for your order. The information we have on file is below:</p>
<p>
<b>Customer Information</b><br />
First Name: <xsl:value-of select="Customer/customerFirstName" /><br />
Last Name: <xsl:value-of select="Customer/customerLastName" /><br />
E-mail: <xsl:value-of select="Customer/customerEmail" /><br />
</p>

<p>
<b>Service Information</b><br />
Confirmation Number: <xsl:value-of select="Service/confirmationNumber" /><br />
Price: <xsl:value-of select="Service/price" /><br />
Date: <xsl:value-of select="Service/date" /><br />
</p>
</div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

And finally the Xalan transformer class:

TemplateTransformer.java
------------------------
import java.io.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;

public class TemplateTransformer {
// constructors
public TemplateTransformer() {}

// methods
public String transform(String xml, String xsltStyleSheetPath) {
String text = "";

TransformerFactory tFactory = TransformerFactory.newInstance();

// Define the source XSL
StreamSource source = new StreamSource(new File(xsltStyleSheetPath));
// Define the source XML
StreamSource sourceXML = new StreamSource(new StringReader(xml));
// Define the result destination
StreamResult result = new StreamResult(new StringWriter());

try {
// Tranform the XML using the XSL
Transformer transformer = tFactory.newTransformer(source);
transformer.transform(sourceXML, result);

StringWriter writer = (StringWriter)result.getWriter();
text = writer.toString();
}
catch (TransformerException te) {
return ""; // yeah, I'm being lazy
}

return text;
}
}

And you're done, it's essentially four lines of code. Specify the source XSL, the source XML and the destination. Then call the transform method, simple as that.

Now some testing code. The following is a simple JSP page that can be used to see the results of the transformation, for simplicity sake I'm assuming the XSLT and XML files are on the local hard drive.

<%@ page language = "java"
import = "java.text.*, java.util.*, java.io.*"
%>

<%
String xmlPath = "c:\\temp\\xslt\\emailMessage.xml";
String xslPath = "c:\\temp\\xslt\\emailMessage_html.xslt";

TemplateTransformer t = new TemplateTransformer();
String result = t.transform(xmlPath, xslPath);
%>

<html>
<head>
<title>XSLT/Xalan Test Page</title>
</head>
<body>
<b>XSL Path:</b> <%= xslPath %><br />
<b>XML Path:</b> <%= xmlPath %><br />
<br />

<b>Result:</b><br />
<pre>
<%= result %>
</pre>
</body>
</html>

Well, hopefully all of that worked and made a little bit of sense.

Tuesday, April 3, 2007

Beginnings

So... I suppose I should say a few words. This is my first go with this type of thing so bear with me through the rough bits. I haven't totally decided on the overall direction of this blog, but I think to start I am going to use it to post topics related to software development. Chances are there will be some other random things thrown in there from time to time, so hopefully I won't bore everybody to tears. Worst case, this will turn into an archive of code snippets at which point I will bore you all.

Now, can I keep this place from getting stagnating? We shall see.