Running web service clients without a web service

One of the challenges with large scale Enterprise Application development is dealing with the dependencies between teams and parts of the system being developed. Despite Agile software development methodologies a waterfall style of producing artifacts can occur. For example, the UI can not be completed because the web services are not built and the web services are not built because the data model is not complete. The data model is not complete because there are outstanding questions that the customer hasn’t answered.

In an ideal world we would all be able to agree the integration interfaces up front and then farm out the development effort so that the UI and Server Side teams can get coding straight away. One way to make this happen is for the UI team to define the WSDL interfaces for the services they plan to invoke. It is good practice for the ‘caller’ to define the interface where possible.

The UI team could also go ahead and provide their own simple implementation. Included in this article is some code for a servlet that accepts a SOAP Envelope request and returns a SOAP Envelope response. It uses the element name in the SOAP Body to look up an XML file with the same name in the classpath and then returns the contents. A client can define a WSDL, set the URL for the Servlet as the SOAP address and provide a ‘canned’ response XML file for each operation. There is also an Enterprise Service Bus (ESB) approach that is outlined as an alternative at the end of the article.

Simple SOAP Servlet
The servlet uses the JAXP libraries…


DocumentBuilderFactory builderFactory
= DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;

public void init() throws ServletException {
try {
this.builderFactory.setNamespaceAware(true);
this.builder = this.builderFactory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
throw new ServletException("Error initialising servlet", e);
}
}

A mechanism to get the SOAP Body from the request is needed. This method is part of that. It is inelegant as getElementsByTagName() just did not work during testing. Probably due to some configuration issue in my environment or codebase. Since the SOAP Envelope might contain a Header element, the Body element may be the second element.


private Element getSOAPBodyElement(Element requestSOAPEnvelope) {
Element firstChild = (Element) requestSOAPEnvelope.getFirstChild();
if (firstChild.getLocalName().equalsIgnoreCase("body")) {
return firstChild;
}
Element secondChild = (Element) firstChild.getNextSibling();
if (secondChild.getLocalName().equalsIgnoreCase("body")) {
return secondChild;
}
return null;
}

The following method is where the real work is done. Most of the effort is spent on making sure that the request is a SOAP Envelope.


private QName getRequestPayLoadQualifiedName(HttpServletRequest request)
throws ServletException, IOException
{
try
{
Document requestXML = this.builder.parse(request.getInputStream());
Element requestSOAPEnvelope = requestXML.getDocumentElement();
if (!requestSOAPEnvelope.getLocalName().equalsIgnoreCase("envelope"))
{
throw new ServletException(
"Unable to parse request. Are you sure it is a SOAP Envelope?"
);
}

Element requestSOAPBody = this.getSOAPBodyElement(requestSOAPEnvelope);
if (requestSOAPBody == null) {
throw new ServletException(
"Unable to parse request. Body element not found. Are you sure it is a SOAP Envelope?"
);
}

Element requestPayload = (Element) requestSOAPBody.getFirstChild();
QName name = new QName(
requestPayload.getNamespaceURI(),
requestPayload.getLocalName());
return name;
} catch (SAXException e) {
throw new ServletException("Unable to parse request. Are you sure it is a SOAP Envelope?", e);
}
}

And finally the doPost method which looks up the file and writes the contents to the response stream. Note that due to the use of getResourceAsStream, the XML file is expected to be in the classpath in the same package as the servlet. Also, the response content must be set to text/xml for a SOAP response.


public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException
{
QName requestPayLoadQualifiedName =
this.getRequestPayLoadQualifiedName(request);
InputStream responseXML = this.getClass()
.getResourceAsStream(
requestPayLoadQualifiedName.getLocalPart() + ".xml");

if (responseXML == null) {
throw new ServletException("Unable to find "
+ requestPayLoadQualifiedName.getLocalPart()
+ ".xml in the classpath.");
}
response.setContentType("text/xml");
int respInt = responseXML.read();
while (respInt != -1) {
response.getOutputStream().write(respInt);
respInt = responseXML.read();
}
}

An example of where this could be used is with a Flex front end where the SWF file is host in a web app. The WAR file could be organised as follows:
/MyApplication.SWF (the Flex front end)
/MyApplication.html (wrapper html which embeds the SWF file)
/MyService.wsdl (WSDL defining the interface for the web service. Has servlet address as endpoint)
/WEB-INF/web.xml (registers the SimpleSOAP class as a servlet)
/WEB-INF/classes/SimpleSOAP.class (the servlet)
/WEB-INF/classes/myOperation.xml (the canned response for a call to ‘myOperation’)

The UI development team can now orchestrate their screens, making web service calls to web services that haven’t been implemented yet. Once they are implemented, the soap address in the WSDL can change. The above servlet could be further worked on with some XPATH expresssions to map certain combination of parameters to responses. One could make it really sophisticated to follow a sequence like a demonstration script. However, putting all that together takes the pressure of the server side team in delivering the real implementation, doesn’t it?

Simple ESB Solution
Another approach would be to use the Enterprise Service Bus and have routing rules to read responses from files. The ESB approach would also allow for more content based routing allowing for different responses to be given depending on parameters passed at runtime. If the development environment is going to involve an Enterprise Service Bus, then the above servlet approach is best limited to individual developers environment or for simple automated component testing of the UI.

JBoss and Oracle XE

JBoss and Oracle XE (Express Edition) make for an interesting, and cost effective, J2EE stack for non-mission critical, small scale, software applications. Getting JBoss and Oracle XE to work together is really straight forward.

Resolve port conflicts
By default, JBoss and Oracle XE both use port 8080. So, when using JBoss and Oracle XE on the same machine, something has got to give. As one is most likely to be using and interacting with the container more, it might as well be the database that has to adapt. To change the default Oracle XE HTTP Listening port (8080) to 9090 do the following:

  1. Start sqlplus (Run SQL Command Line icon in windows)
  2. Enter ‘connect / sysdba’
  3. Enter ‘exec dbms_xdb.sethttpport(9090);’
  4. Stop and then Start the Oracle XE database

Note that this does not change the default TNS Listening port 1521, although the short cut (/app/oracle/product/10.2.0/server/Database_homepage.url) to launch the Database home page will need to be updated.

Setup DataSource
The Oracle XE installation comes with a sample HR database. A DataSource in JBoss can be defined for it, but first the Oracle JDBC library needs to be in the JBoss server classpath. Copy ojdbc14.jar from /app/oracle/product/10.2.0/server/jdbc/lib to /server/default/lib. Now the DataSource can be defined. DataSources are ‘deployed’ in JBoss. Their configuration information is in an XML file with a name that ends in ‘-ds’.

In /server/default/deploy create a file called oraclexe-ds.xml with the following content:









OracleXEDS

jdbc:oracle:thin:@127.0.0.1:1521:XE

oracle.jdbc.driver.OracleDriver
hr
hr

5
100


org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter


Remember that in Unlocking the Sample User Account step in Oracle XE Getting Started Guide, the HR account password is set to ‘hr’. The console for JBoss should display something like:


[ConnectionFactoryBindingService] Bound ConnectionManager 'jboss.jca:service=DataSourceBinding,name=OracleXEDS' to JNDI name 'java:OracleXEDS'

Testing DataSource witha JDBC client
A simple JSP, in an expanded WebApp, can be used to test the DataSource. In /server/default/deploy create a directory called ‘jdbcclient.war’. In that directory create a file called ‘client.jsp’ and add the following content:

<%@page contentType="text/html"
import="java.util.*,javax.naming.*,javax.sql.DataSource,java.sql.*"
%>
<%

DataSource ds = null;
Connection con = null;
PreparedStatement pr = null;
InitialContext ic;
try {
ic = new InitialContext();
ds = (DataSource)ic.lookup( "java:/OracleXEDS" );
con = ds.getConnection();
pr = con.prepareStatement("SELECT EMPLOYEE_ID, LAST_NAME FROM EMPLOYEES");
ResultSet rs = pr.executeQuery();
while (rs.next()) {
out.println("
" +rs.getString("EMPLOYEE_ID") + " | " +rs.getString("LAST_NAME"));
}
rs.close();
pr.close();
}catch(Exception e){
out.println("Exception thrown " +e);
}finally{
if(con != null){
con.close();
}
}
%>

Open your browser and point it to http://localhost:8080/jdbcclient/client.jsp. A list of employee numbers and last names get displayed. This ‘jdbcclient’ approach is used in the JBoss DataSource tutorials.

Changing post-installation configuration for Oracle Access Manager Identity Server

Oracle Access Manager is an enterprise scale solution for both centralized identity management and access control. It integrates out-of-the-box with all leading directory servers, application servers, web servers, and enterprise applications. By protecting resources at the point of access and delegating authentication and authorization decisions to a central authority, Access Manager helps secure web, J2EE, and enterprise applications. It also provides self service administration functionality, complying with the authentication and authorization policies that are defined centrally. Not only that, Access Manager has API’s for customisation and integration, making it possible address a number of functional and non-functional requirements for security solutions in different industries. However, it’s most topical feature is it’s Single Sign-on capabilities. Making it a very attractive solution for enterprise deployment of SOA software solutions.

As you would expect with software that does so much, there is a lot involved in setting up Oracle Access Manager. Although it is not very complicated, there are a significant number of steps which have to be done right. Thankfully, these steps are set out in an Oracle By Example series which provides step-by-step instructions on how to perform a variety of tasks by integrating Oracle Virtual Directory with Oracle Access Manager.

When setting up Identity Server and Web Pass there is a post-installation configuration sequence which is really straight forward. However, if you make a mistake, which is not addressed before the setup completes, how do you change these settings? Here’s how…

The post-installation configuration process involves a number of screens. The status of the configuration is maintained by the Identity Server in identity/oblix/config/setup.xml. To trick the Identity Server to take you through the post-installation configuration process again when you click on the ‘Identity System Console’, you have to edit this file.

Simply comment out the ‘status’ NameValPair element. Save the file and restart both the Identity Server and HTTP Server. Then, go back over the Postinstallation Configuration for Oracle Access Manager Identity Server as normal. Voilà!

Practices of an Agile Developer



Title: Practices of an Agile Developer

Authors: Venkat Subramaniam & Andy Hunt
Publisher: Pragmatic Bookshelf

If you are looking for a step by step guide on running your software development projects, THIS IS NOT THE BOOK! This book, published in 2006 but still very valid today, collects the personal habits, ideas, and approaches of successful agile software developers and presents them in a series of short, easy-to-digest tips. There are 45 tips in all, covering a broad range of subjects such as the development process , incremental learning, etc. The format taken for each tip is quite interesting. As well as the indepth explanation and case study references, each tip has:

  • A taunt from the devil. That voice in your head that seems perfectly reasonable, but is infact taking you to a world of pain in the future.
  • Advice from your guardian angel. The counter-argument to the devil’s shenanigans.
  • A ‘What it feels like’ section. Nice short description of what happens when the tip is applied.
  • A ‘Keeping your balance’ section. This really reflects the Agile Development philosophy of adapting to the circumstances.

The authors have taken this approach out of the firm belief that the most important part of software development takes place in the developers head, so there is little focus on tools. However, they do provide a little sidebar called the Agile Toolkit which outlines the uses for:

  • Wiki
  • Version Control
  • Unit Testing
  • Build Automation & Continuous Integration

These tools support Agile Development, which the book describes as follows:
Agile Development uses feedback to make constant adjustments in a highly collaborative environment. Emphasis is mine, but I think this is a very good definition.

To summarise, Practices of an Agile Developer provides pragmatic ways of approaching the development process and your personal coding techniques as well as your own attitudes, issues with working on a team, and how to best manage your learning.

Oracle XE default port and windows firewall

SOA Suite 11g Technology Preview 3 needs an Oracle database and Oracle XE (the free database edition) is ideal as the installation is so straight forward. By default the installation sets the database listener port to 1521 and the http server port to 8080. If these ports are already in use on your machine, the installer will prompt you to specify an available port number.

Figure 1. Choosing another port number. This dialog box only gets displayed during installation if port is in use or blocked by firewall.

On a Windows XP installation the Oracle XE installer reports that a port is in use if that port number is being blocked by the firewall. Disabling the firewall is generally not a good idea as, along with anti-virus software, it provides a crucial defence for your machine, network and business.

The windows firewall settings can be found in the Control Panel. Just add the default port numbers to the firewall exception list. Once that is done, one can switch back to the ‘Choose Port’ dialog, put the default value in and continue with the Oracle XE installation.

Figure 2. Keep the firewall ‘On’ and go to the Exceptions list.
Figure 3. Adding the Oracle XE port 1521 to the Exceptions list.