Archive for the ‘Tech’ Category

JAX-RS (using Apache CXF) in embedded Tomcat example

Tuesday, January 13th, 2015

I had serious trouble today firing up an embedded Tomcat server that serves up REST resources using JAX-RS via Apache CXF.

Here’s minimal example, hopefully saving you the same trouble:

src/HelloJaxRs.java:

import org.apache.catalina.startup.Tomcat;
import org.apache.catalina.Context;
import org.apache.catalina.Wrapper;

public class HelloJaxRs
{
    public static void main( String[] args ) throws Exception
    {
        Tomcat tomcat = new Tomcat();
        Context context = tomcat.addContext( "/", "" );

        Wrapper servlet = context.createWrapper();
        servlet.setName( "jaxrs" );
        servlet.setServletClass(
            "org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet" );

        servlet.addInitParameter(
            "jaxrs.serviceClasses",
            Hello.class.getName()
        );

        servlet.setLoadOnStartup( 1 );
        context.addChild( servlet );
        context.addServletMapping( "/rest/*", "jaxrs" );

        tomcat.start();
        tomcat.getServer().await();
    }
}

src/Hello.java:

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;

@Path( "/hello/{name}" )
public class Hello
{
    @GET
    public String getThing( @PathParam( "name" ) String name )
    {
        return "Hello, " + name;
    }
}

build.xml:


<?xml version="1.0" encoding="UTF-8"?>
<project default="run">

    <target name="run" depends="compile">
        <mkdir dir="bin/tomcat.8080/webapps"/>
        <java
            classname="HelloJaxRs"
            fork="true"
            failonerror="true"
            dir="bin"
        >
            <classpath>
                <pathelement location="bin/"/>
                <fileset dir="lib"><include name="**/*.jar"/></fileset>
            </classpath>
        </java>
    </target>

    <target name="compile">
        <mkdir dir="bin"/>
        <javac srcdir="src" destdir="bin">
            <classpath>
                <fileset dir="lib"><include name="**/*.jar"/></fileset>
            </classpath>
            <compilerarg value="-Werror"/>
        </javac>
    </target>

</project>

To download the dependencies (or you can do something clever with Maven):

$ mkdir lib
$ cd lib
$ wget http://www.webhostingjams.com/mirror/apache/tomcat/tomcat-7/v7.0.57/bin/apache-tomcat-7.0.57.tar.gz
$ tar -xzf apache-tomcat-7.0.57.tar.gz
$ wget http://www.apache.org/dyn/closer.cgi?path=/cxf/3.0.3/apache-cxf-3.0.3.tar.gz
$ tar -xzf apache-cxf-3.0.3.tar.gz
$ cd ..

To run Tomcat:

$ ant

Then, in another terminal, you can see it’s working:

$ curl http://localhost:8080/rest/hello/andy
Hello, andy

Vim persistent buffer list combined with saved sessions

Thursday, January 8th, 2015

I like to use several saved Vim sessions to remember what files I was working on in a particular project.

I also like to have a list of buffers I have open on the left-hand side of the screen that is always visible and up-to-date.

Sometimes, the existence of a generated buffer like the list of buffers can confuse the session restore code, but I have found a way to make this work nicely using the Buffergator plugin and the built-in mksession command.

Here are the relevant snippets from my .vimrc.

I am a beginner: please comment if you see bugs or possible improvements.

" Prerequisites: install the Buffergator plugin


" Save session on exit, excluding problematic stuff like options

set sessionoptions=blank,buffers,curdir,tabpages,resize,winpos,winsize
au VimLeavePre * if v:this_session != '' | exec "mks! " . v:this_session | endif


" Open Buffergator when you press F5

nnoremap <F5> :BuffergatorOpen<CR>


" Various Buffergator options to make it persistent,
" and displayed how I like

let g:buffergator_autodismiss_on_select = 0
let g:buffergator_display_regime = "bufname"
let g:buffergator_sort_regime    = "filepath"
let g:buffergator_autoupdate = 1


" Suppress the error message about the Buffergator buffer
" when you restore a session

function! OpenBuffergatorIfItsBufferExists()
    if bufnr("[[buffergator-buffers]]") > ''
        BuffergatorOpen
        normal o
    endif
endfunction

autocmd VimEnter * call OpenBuffergatorIfItsBufferExists()

Now when I start vim with vim -S path/to/session.vim the session is restored and saved when I exit, with a persistent buffer list on the left, and no errors during the session restore.

Encoding URLs in Java

Thursday, December 4th, 2014

To encode a URL in Java, create a new instance of java.net.URI and then call toString() or toASCIIString() on it.

DO NOT use java.net.URLEncoder. It is for HTML form encoding, not encoding URLs, despite its name.

Each part of a URL must be escaped differently, so use the multi-argument constructors for URI where you have multiple parts you want to stick together. You can pass in null for arguments you want to omit, and it works the way you’d hope.

This program:

class EncodeUrls
{
    public static void main( String[] args ) throws java.net.URISyntaxException
    {
        url( "http", "example.com", "/x/y/x", "x=y", "pos" );

        url(
            "http",
            "exa\uD83D\uDCA9mple.com",
            "/x/\uD83D\uDCA9/x",
            "x=\uD83D\uDCA9",
            "po\uD83D\uDCA9"
        );
    }

    private static void url(
        String scheme,
        String host,
        String path,
        String query,
        String fragment
    )
    throws java.net.URISyntaxException
    {
        java.net.URI uri = new java.net.URI(
            scheme, host, path, query, fragment );

        System.out.println( "." + uri.toString() );
        System.out.println( "." + uri.toASCIIString() );
        System.out.println();
    }
}

prints:

.http://example.com/x/y/x?x=y#pos
.http://example.com/x/y/x?x=y#pos

.http://exa💩mple.com/x/💩/x?x=💩#po💩
.http://exa%F0%9F%92%A9mple.com/x/%F0%9F%92%A9/x?x=%F0%9F%92%A9#po%F0%9F%92%A9

LibreOffice spell check not working in Lubuntu

Wednesday, November 12th, 2014

I installed LibreOffice into Lubuntu, but the spell checking didn’t work.

It turns out I need to install a dictionary for my locale:

sudo apt-get install myspell-en-gb

I needed to restart LibreOffice, and then I got spell checking as I typed.

Is it ok to represent dates as Unix time (seconds since the epoch) in JSON?

Thursday, November 6th, 2014

Yes.

If your JSON contains integer numbers that represent Unix time (seconds since the “epoch”), and you parse your JSON to JavaScript, the range of integers that can accurately be represented is -9007199254740992 to 9007199254740992 (ref: EcmaScript standard, section 8.5).

The year 4000AD starts at unix time 64060588815, which is 9007135194152192 less than the maximum.

The year 1AD started at unix time -2177452800, which is 9007197077288192 more than the minimum.

So there are enough numbers.