Monthly Archives: September 2015

Beware of changing variable names in SOAP Webservices

When improving upon your SOAP webservices currently in production, it might occur to you to change variable names in method signatures to make the more readable and conform to your coding practices. After these are the small incremental improvements we make to reduce our technical debt. But before doing this, please beware of the ramifications.

A WSDL describing a SOAP webservice is “strongly typed” in the sense that method signatures including method names, variable names and their types, once defined, cannot be changed with breaking backward compatibility. And Since SOAP does not provide an easy way for clients to detect an API change, altering either of the constructs that define your WSDL guarantees a temporal disruption of service due to your current API consumers.

For example, say you have a SOAP webservice exposing this method:

public Report GetReport(string ReportName)

which is defined as part of your WSDL. If you later change this this method to say

public Report GetReport(string reportName)

the service will receive null as the reportName in some client implementations. Others may simply crash since this endpoint is no longer known. If one is spending quite some time working with SOAP based services on a daily basis, it becomes almost of a second nature to regenerate the client proxy based on the published WSDL to ensure consistency otherwise, you get these strange behaviors. However, if you are spending a lot of time in RESTFul services, chances are you are not worrying about these types of problems. In this case, there is a good chance you will rename a webservice API parameter name in the name of improving readability (nothing wrong with that) only to find out that the next morning none of your clients are able to connect to your API.

And no, unit tests will not catch this.

Installing Python request module on Windows

Assume you had a script that started as follows:

#!/usr/bin/python

import requests
from requests.auth import HTTPBasicAuth

If you have a bare bones Python install on Windows and you attempt to run this script, you will run into the following error:

ImportError: No module named requests

What do need to do is install the Python module called “requests”. To this do, please follow these steps, assuming you have Python 2.7:

1. Download the Python request module, requests-2.7.0.tar.gz (md5).
2. Use a 7zip or similar to fully extract the package to request-2.7.0.

If you are using Windows recommended downloads location, the extracted package will be in

C:\Users\[username]\Downloads\requests-2.7.0.tar\dist\requests-2.7.0\requests-2.7.0

3. Launch a command prompt and navigate to c:\python27\scripts.
4. Type the following command at the prompt:

pip install C:\Users\[username]\Downloads\requests-2.7.0.tar\dist\requests-2.7.0\requests-2.7.0

If successful, you should see the following messages at the command prompt:

Processing c:\users\knji\downloads\requests-2.7.0.tar\dist\requests-2.7.0\requests-2.7.0
Installing collected packages: requests
Running setup.py install for requests
Successfully installed requests-2.7.0

5. Now, if you run your original Python script, it should no longer complain about not being able to import the request module.

Hibernate annotation to the rescue when mapping files cannot be located

Forget hibernate mapping files, seriously unless you really need to. Use annotations instead. Then you need not worry about running into class path issues.

This is the story:

I wanted to create a simple RESTFul service which exposes simple CRUD functionality on data within a PostgreSQL database. In a previous post,
I briefly covered using Hibernate to connect to a PostgreSQL database to retrieve entities within the context of a RESTful webservice. This all worked flawlessly since the deployment target was IntelliJ’s embedded http server. When it came time to deploy the resulting .war to a local Tomcat instance, all hell broke loose.

I used the the Jersey archetype for Maven which gave provided a directory structure like this:

|- src
   |- main
      |- java
         |-my-app
            - User.java
            - HibernateUtils.java
            .......
      |- resources
          - hibnernate.cfg.xml
          - user.hbm.xml

As stated earlier, everything worked as expected when deployed to IntellJ’s local http server. However, when .war file was deployed to a local Tomcat instance on the same box, hibernate was not able to find a mapping for the user entity. The error was

User is not mapped [from User where id > :id]

for a class defined as follows:

public class User {
    private int id;
    private String _firstName;
    private String _lastName;

    public String getFirstName(){
        return _firstName;
    }
    public void setFirstName(String name){
        _firstName = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getLastName() {
        return _lastName;
    }

    public void setLastName(String _lastName) {
        this._lastName = _lastName;
    }

    @Override public String toString(){
        return String.format("%s %s", _firstName, _lastName);
    }
}

The hibernate files were all in place and mappings were all correct. After spending a couple of days and not seemingly getting anywhere, questioning my sanity, I decided on another approach: annotations. After all, this is the common pattern when using the Entity Framework in .NET.

The User class was modified as follows:

import javax.persistence.*;

/**
 * Created by Klaus on 31/08/2015.
 */
@Entity
@Table( name = "users" )
public class User {

    @Id
    @GeneratedValue
    private int id;

    @Column (name = "firstname")
    private String _firstName;

    @Column (name = "lastname")
    private String _lastName;

    /* rest of code ignored for brevity */
}

HibernateUtils was also modified:

public class HibernateUtils {
    private static SessionFactory sessionFactory;

    public static SessionFactory getSessionFactory() {

        if (sessionFactory == null) {
            // loads configuration and mappings
            Configuration configuration =
                    new Configuration()
                            .addAnnotatedClass(User.class)
                            .configure();

            ServiceRegistry serviceRegistry
                    = new StandardServiceRegistryBuilder()
                    .applySettings(configuration.getProperties()).build();

            // builds a session factory from the service registry
            sessionFactory = configuration.buildSessionFactory(serviceRegistry);
        }

        return sessionFactory;
    }

Repacking, deploying to IntelliJ’s local http server ensured functionality was not broken. Next, deploying to a local instance of Tomcat on the local machine, also proved successful. This left me pondering for a while…. but there are things to get done…

What happened here remains a mystery which begs for an explanation. Could a unit test have saved me endless hours deploying to Tomcat?