Aug 19 2014

POST with Apache HttpClient 4

There is a vast difference between using HttpClient 3 and HttpClient 4. None of the documentation I found for HttpClient 4 had a full example of using POST with connection and socket timeout set. So I have included a full example here. For this code I used httpclient-4.3.2.jar which also needed httpcore-4.3.1.jar. I use IVY for dependency management and this entry in ivy.xml got me what I needed:

<dependency org="org.apache.httpcomponents" name="httpclient" rev="4.3.2"/>

Take a look at the Javadoc for RequestConfig.Builder for what other options are available.

If you need to convert the InputStream from the response to a String I have a quick how-to for that.

 public void executePost(String destinationUrl, Map<String, String> pairs) {
        //Set any needed config options, here is how you would set connection and socket timeout
        RequestConfig.Builder configBuilder = RequestConfig.custom();
        configBuilder.setConnectTimeout(2000);
        configBuilder.setSocketTimeout(2000);

        //Create a List of BasicNameValuePairs, here I am doing it from a Map that was passed in. Do whatever
        //it is you need to do
        List<NameValuePair> nameValuePairs = new ArrayList<>(pairs.size());
        for (Map.Entry<String, String> entry : pairs.entrySet()) {
            nameValuePairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
        }

        //Create an HttpPost and set your config builder here if you have any custom settings
        HttpPost post = new HttpPost(destinationUrl);
        post.setConfig(configBuilder.build());

        try {
            //Create an encoded form entity and assign it to the HttpPost object
            UrlEncodedFormEntity entity = new UrlEncodedFormEntity(nameValuePairs, Consts.UTF_8);
            post.setEntity(entity);

            //Execute the post, this returns an HttpResponse if all is well or throws an exception if one of the
            //timeout values are met
            HttpResponse httpResponse = this.localHttpClient.get().execute(post);
            int statusCode = httpResponse.getStatusLine().getStatusCode();
            if (statusCode >= 200 && statusCode <= 299) {
                //2xx is success, handle them as success. Or handle specific status codes, whatever the case
                //may be

                InputStream responseStream = httpResponse.getEntity().getContent();
                //Do something with the responseStream, convert it to a String, pass it to an XML parser, whatever
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            post.releaseConnection();
        }
    }

Aug 19 2014

Quick How-To: Convert InputStream to String

I find myself having to convert an InputStream to a String on occasion. It isn’t something I do super-frequently so I usually have to go hunt down some code where I have done it before. Here it is for quick reference for myself and whoever else. This code uses a Java 1.7 try-with-resources statement. If you aren’t using Java 1.7+ you will of course need to use the correct try syntax for prior versions of Java with a finally block.

 public String readBody(InputStream inputStream) throws Exception {
        StringWriter writer = new StringWriter();

        char[] buffer = new char[1024];
        try (Reader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"))) {
            int n;
            while ((n = reader.read(buffer)) != -1) {
                writer.write(buffer, 0, n);
            }
        }

        return writer.toString();
    }

Jul 05 2013

Subversion: Compile Subversion 1.8 on Mac OS 10.8 or 10.9

To compile Subversion 1.8 on Mac OS 10.8 (Mountain Lion) only requires the compilation of one dependency. Prior to 1.8 Subversion used neon for HTTP requests. It now uses Serf. If you access any repositories via HTTP you must first download and compile Serf.

If you compile Subversion without Serf being present and then try to access a repository via HTTP you get an error that looks something like this:

svn: Unrecognized URL scheme for http://www.example.com/svn/some_respository

Compiling Serf

First you need to download Serf which can be downloaded from http://code.google.com/p/serf/downloads/list. I used version 1.2.1 which was the most recent at the time I compiled it.

Generally compiling something is as easy as ./configure && make && sudo make install; however, for some reason Serf tries to use the wrong compiler by default. I am sure a C programmer could explain why; however, I am not one so I won’t attempt to explain. I will just tell you how to fix it. If you try to run “./configure” you will get the error message:

checking for gcc… /Applications/Xcode.app/Contents/Developer/Toolchains/OSX10.8.xctoolchain/usr/bin/cc
checking whether the C compiler works… no
configure: error: in `/Users/mjparme/temp/serf-1.2.1′:
configure: error: C compiler cannot create executables
See `config.log’ for more details

To fix this you need to create a symbolic link to point it at the correct compiler, so execute this command:

sudo ln -s /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain /Applications/Xcode.app/Contents/Developer/Toolchains/OSX10.8.xctoolchain

For Mavericks (10.9) this symbolic link should be

sudo ln -s /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain /Applications/Xcode.app/Contents/Developer/Toolchains/OSX10.9.xctoolchain

Now you can run ./configure with no errors.

  1. Donwload Serf http://code.google.com/p/serf/downloads/list
  2. Unzip the downloaded file: unzip serf-1.2.1.zip (or “tar xvfz serf-1.2.1.tar.bz2″ if you downloaded the bzip one)
  3. cd serf-1.2.1
  4. Execute: ./configure && make -j 5 && sudo make install

Note that the value you pass for the -j parameter should be number of cores + 1 (this is the general consensus and my totally unscientific benchmarking supports the consensus). So if you have a dual-core machine, pass 3, quad-core pass 5, etc.

Also note that newer versions of the tar command can unzip files compressed with bzip2 as well as gzip with the “z” option.

Compile Subversion 1.8

Now since the Serf stuff is taken care of you can compile Subversion 1.8 that includes HTTP support like you would most any other app written in C.

  1. Download the source here: http://subversion.apache.org/download/
  2. Unzip the downloaded file: unzip subversion-1.8.0.zip (or “tar xvfz subversion-1.8.0.tar.gz” or “tar xvfz subversion-1.8.0.tar.bz2″ depending on which one you downloaded)
  3. cd subversion-1.8.0
  4. ./configure –with-serf=/usr/local/serf && make -j 5 && sudo make install

By default Subversion is installed in /usr/local/bin. Note that Mac OS 10.8 comes with subversion 1.6.18 installed in /usr/bin. To insure your compiled version is the one executed make sure /usr/local/bin appears in your PATH before /usr/bin.

So if you are using bash as your shell, add this to .bashrc in your home directory:

PATH=/usr/local/bin:$PATH
export PATH

Jul 03 2013

Weblogic: Grails index.gsp not found

If you try to deploy a Grails application to Weblogic and try to go to “/” in the app you will get the message:

“/index.gsp” not found.

This definitely affects Weblogic 9. and 10.x. I am unsure if it is a problem with later versions. The fix is a simple addition to the UrlMappings.groovy file. Add the line:

"/index.gsp"(view:"/index")

So that it looks like this:

class UrlMappings {
	static mappings = {
		"/$controller/$action?/$id?"{
			constraints {
				// apply constraints here
			}
		}

		"/"(view:"/index")
		"500"(view:'/error')
        "/index.gsp"(view:"/index")
	}
}

See: 

http://jira.grails.org/browse/GRAILS-8767

Jul 03 2013

Grails: Deploy Grails 2.x or newer application to Weblogic 9

If you try to deploy a Grails application built with Grails 2.0 or greater to Weblogic 9.0 it will fail. There are two things you need to do to get a Grails 2.0 application to deploy to Weblogic 9. These occur because of Weblogic 9′s use of Java 1.5.

As an overview the 2 things you need to do are:

  1. Change the XML schema declaration in the generated web.xml file to use Servlet specification 2.4 rather than 2.5
  2. Put the JAXB jars in the lib folder of the project

Change XML schema declaration of web.xml

Starting with Grails 2.0 the XML Schema declaration in web.xml is for Servlet spec 2.5:

<web-app version=”2.5″  metadata-complete=”true” xmlns=”http://java.sun.com/xml/ns/javaee” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:schemaLocation=”http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd”>

Your app will not deploy to Weblogic 9 with this declaration in your web.xml. You will get an exception that looks like this:

[HTTP:101064][WebAppModule(ivrtester:ivrtester.war)] Error parsing descriptor in Web appplication weblogic.application.ModuleException: Unmarshaller failed at weblogic.servlet.internal.WebAppModule.loadDescriptor(WebAppModule.java:781) at weblogic.servlet.internal.WebAppModule.prepare(WebAppModule.java:272) at weblogic.application.internal.flow.ScopedModuleDriver.prepare(ScopedModuleDriver.java:176) at weblogic.application.internal.flow.ModuleListenerInvoker.prepare(ModuleListenerInvoker.java:93) at weblogic.application.internal.flow.DeploymentCallbackFlow$1.next(DeploymentCallbackFlow.java:360) at weblogic.application.utils.StateMachineDriver.nextState(StateMachineDriver.java:26) at weblogic.application.internal.flow.DeploymentCallbackFlow.prepare(DeploymentCallbackFlow.java:56) at weblogic.application.internal.flow.DeploymentCallbackFlow.prepare(DeploymentCallbackFlow.java:46) at weblogic.application.internal.BaseDeployment$1.next(BaseDeployment.java:615) at weblogic.application.utils.StateMachineDriver.nextState(StateMachineDriver.java:26) at weblogic.application.internal.BaseDeployment.prepare(BaseDeployment.java:191) at weblogic.application.internal.DeploymentStateChecker.prepare(DeploymentStateChecker.java:147) at weblogic.deploy.internal.targetserver.AppContainerInvoker.prepare(AppContainerInvoker.java:61) at weblogic.deploy.internal.targetserver.operations.RedeployOperation.createAndPrepareContainer(RedeployOperation.java:98) at weblogic.deploy.internal.targetserver.operations.RedeployOperation.doPrepare(RedeployOperation.java:118) at weblogic.deploy.internal.targetserver.operations.AbstractOperation.prepare(AbstractOperation.java:217) at weblogic.deploy.internal.targetserver.DeploymentManager.handleDeploymentPrepare(DeploymentManager.java:718) at weblogic.deploy.internal.targetserver.DeploymentManager.prepareDeploymentList(DeploymentManager.java:1185) at weblogic.deploy.internal.targetserver.DeploymentManager.handlePrepare(DeploymentManager.java:247) at weblogic.deploy.internal.targetserver.DeploymentServiceDispatcher.prepare(DeploymentServiceDispatcher.java:157) at weblogic.deploy.service.internal.targetserver.DeploymentReceiverCallbackDeliverer.doPrepareCallback(DeploymentReceiverCallbackDeliverer.java:157) at weblogic.deploy.service.internal.targetserver.DeploymentReceiverCallbackDeliverer.access$000(DeploymentReceiverCallbackDeliverer.java:12) at weblogic.deploy.service.internal.targetserver.DeploymentReceiverCallbackDeliverer$1.run(DeploymentReceiverCallbackDeliverer.java:45) at weblogic.work.ServerWorkManagerImpl$WorkAdapterImpl.run(ServerWorkManagerImpl.java:518) at weblogic.work.ExecuteThread.execute(ExecuteThread.java:209) at weblogic.work.ExecuteThread.run(ExecuteThread.java:181) Caused by: com.bea.xml.XmlException: failed to load java type corresponding to e=web-app@http://java.sun.com/xml/ns/javaee at com.bea.staxb.runtime.internal.UnmarshalResult.getPojoBindingType(UnmarshalResult.java:325) at com.bea.staxb.runtime.internal.UnmarshalResult.determineTypeForGlobalElement(UnmarshalResult.java:292) at

To fix this the declaration needs to be changed to a Servlet spec 2.4 declaration. However, by default you can’t see the web.xml that Grails packages into the war file. This web.xml file is included in the templates, so to get it execute:

grails install-templates

This will put the templates under the src/ directory. The web.xm file is found at src/templates/war/web.xml edit web.xml and change the opening web-app tag to:

<web-app xmlns=”http://java.sun.com/xml/ns/j2ee” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:schemaLocation=”http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd” version=”2.4″>

When you do a grails war this web.xml will be used and this fixes the first deployment problem.

Put JAXB in the lib/ directory

The next problem is that Weblogic 9 requires Java 1.5 which does not include JAXB which wasn’t included in the JDK until Java 1.6 (in Update 3 if I recall correctly). Starting with Grails 2.0 JAXB appears to now be a required dependency (or it always was but Grails just stopped including it with Grails since it is included in Java 1.6 now).

If you do not include JAXB in lib/ you will get an exception that looks like this:

weblogic.application.ModuleException:
at weblogic.servlet.internal.WebAppModule.startContexts(WebAppModule.java:891)
at weblogic.servlet.internal.WebAppModule.start(WebAppModule.java:333)
at weblogic.application.internal.flow.ModuleStateDriver$3.next(ModuleStateDriver.java:204)
at weblogic.application.utils.StateMachineDriver.nextState(StateMachineDriver.java:26)
at weblogic.application.internal.flow.ModuleStateDriver.start(ModuleStateDriver.java:60)
Truncated. see log file for complete stacktrace
java.lang.InternalError: erroneous handlers
at org.hibernate.validator.xml.ValidationXmlParser.parseValidationXml(ValidationXmlParser.java:60)
at org.hibernate.validator.engine.ConfigurationImpl.parseValidationXml(ConfigurationImpl.java:252)
at org.hibernate.validator.engine.ConfigurationImpl.buildValidatorFactory(ConfigurationImpl.java:143)
at javax.validation.Validation.buildDefaultValidatorFactory(Validation.java:111)
at org.hibernate.cfg.beanvalidation.TypeSafeActivator.getValidatorFactory(TypeSafeActivator.java:380)
Truncated. see log file for complete stacktrace

This one is actually quite easy to fix. Just download JAXB from https://jaxb.java.net, unzip it and copy jaxb-api.jar, jaxb-impl.jar, jaxb-xjc.jar, and jaxb1-impl.jar to the lib/ directory in your project. Any jars in the lib/ directory automatically get added to WEB-INF/lib in the generated war file.

You could alternatively try to get JAXB from IVY. For some reason I remember having issues with this working. However, I can’t recall the exact problem I had right now. So you can try adding this to Build.config in the dependencies closure. You should of course change the version numbers to the one you want.

runtime ‘com.sun.xml.bind:jaxb-impl:2.1.12′,
‘com.sun.xml.bind:jaxb-xjc:2.1.12′,
‘com.sun.xml.bind:jaxb1-impl:2.0.3′

You only need to do one or the other. Either put the jars directory in lib/ or try using IVY.

This should fix the final problem with getting a Grails 2.x app to deploy to Weblogic. I have used this to deploy a Grails 2.0.1 and Grails 2.2 application to Weblogic 9.

Older posts «