Germany

Well we are back on the Moselle which to us is better than the Rhein or Main.

We had a interesting walk yesterday, it was supposed to be up the river over a bridge and back down the other side. With not having walking maps for every area it all went a little wrong. In a vineyard the signs were missing and we ended up doing a high level walk. But at least the views were good. time we got back down to the river it was 3.30 and 8 miles back to camp. So we did the only thing any self respecting Englishman would do. We went for a beer and then caught a bus.

Feeling left out

We are on a site with 240 pitches. there are 6 German outfits, 233 flatlanders and 1 Brit, and we are the only ones without bikes, and 14 of us are not wearing clogs.

Germany

The Rhein between Frankfurt and Koblenz is a bit like a marine motorway with boat tours. It is very busy as a commercial artuary with all the trappings that come with tourism. The pictures you see in books of boats and castles along high cliffs, is actually only a 40mile stretch between Koblenz and Bingen.

One tricky point about the Rhein and its tributary’s is flooding as you can see while we were there the river levels where high, but not as high as it gets as electric boxes in campsites are located about 6ft off the ground, and a lot of buildings like the restaurant on this site are built on stilts

Classic Domino Search Trick

There is less classic Domino work around then there used to be ( Pure Java, mobile and Xpages taking up most of my time), but still plenty of maintenance work for those who can provide what the client wants, any way, this is something I just updated on an existing clients classic app, and it struck me that it MUST be known by just about every one, but either no one has blogged it, or my Google foo is weak at the moment, so I decided to post it in case I might be of some use.

Problem: you have a classic search form, and you want to analyse or work with the results (making totals or stuff like that), but need to somehow get hold of the values in order to do so, I can remember this being a complete PITA years ago, but with a fresh set of eyes its dead easy.

Solution:

1) Make your searching view a HTML one (via the view properties).

2) Make a column that returns a hidden field for each row for the value(s) that you want to access.

"<td>" + "<input name="PostCodeSearchValue"  value="" + PostCode + "" type="hidden" />" + "</td>"

3) Now when you search, you can go a fetch all these values with client side java script.

var coll = document.getElementsByName("PostCodeSearchValue");
var arr = [];
for (var i = 0; i < coll.length; i++) { 
 arr[i] = document.getElementsByName("PostCodeSearchValue").item(i).value;
 }

and do what ever you want with them.

Now that lacked a bit description wise, so here is a demo and working download for you to take to bits

Demo: Here , Just Click “Search” to get a bunch of data to work with and then “Find Unique Postcodes” to run a bit of Javascript over the result to find and display the unique Post Codes in the returned data

DownLoad: You can get the file Here

ahhh, History…

update: Matt White has pointed out that this produces invald HMTL (working but invalid), and suggests using a JS framework and doing the same sort of “find” but using a CSS Class name… a fine point

Old Comments
————
##### Mark(07/06/2012 16:24:22 GDT)
Does that mean you are making a separate search call? rather than a local bit of JS dealing with the data you already have? if you were wanting to total a value for the items the existing search had returned how would you be doing that in the context of a $$search form?
##### Mark Barton(07/06/2012 15:59:29 GDT)
Yes – rather than HTML in the search view columns just construct JSON data, or am I missing something?
##### Mark Barton(07/06/2012 15:28:30 GDT)
Couldn’t you just return JSON?
##### Mark(07/06/2012 15:31:32 GDT)
as part of the search form data?

Being nice to other developers with REST services

REST services are really nice, really fast and easy to create, but sometimes we forget in our haste to get them out the door that a little bit of structure will help both our selves and any third party developer than might user them, eg, if when a call is made to your service

[]

is returned, what does that mean? was it sucessfull but there is no data, or was there an error in your call, a bit of context would go a long way, the easiest way round this is a little wrapper class, nothing fancy, just enough to throw the front end devs a bone, my basic one looks like this

package com.ldc.classes;
public class RESTReturn {  
    public static final Integer SUCCESS = 0;
    public static final Integer FAILED_GENERAL = 1;
    public static final Integer FAILED_INVALID_PARAMETER_VALUES = 2;
    public static final Integer FAILED_MISSING_PARAMETER = 3;
    public static final Integer FAILED_AUTHENTICATION_FAILURE = 4;
    public static final Integer FAILED_AUTHORISATION_FAILURE = 5;
    public static final Integer FAILED_AUTHENTICATION_EXPIRED = 6;
    public RESTReturn() {
    }
    public RESTReturn(int returnStatusParm) {
        returnStatus = returnStatusParm;
        returnStatusDesc = statusToString(returnStatusParm);
    }
    private int returnStatus;
    private String returnStatusDesc;
    private Object payload;
    public int getReturnStatus() {
        return returnStatus;
    }
    public void setReturnStatus(int returnStatus) {
        this.returnStatus = returnStatus;
    }
    public String getReturnStatusDesc() {
        return returnStatusDesc;
    }
    public void setReturnStatusDesc(String returnStatusDesc) {
        this.returnStatusDesc = returnStatusDesc;
    }
    public Object getPayload() {
        return payload;
    }
    public void setPayload(Object payload) {
        this.payload = payload;
    }
    public static String statusToString(Integer wsReturn) {
        if (SUCCESS.equals(wsReturn)) {
            return "It Worked";
        } else if (FAILED_GENERAL.equals(wsReturn)) {
            return "Error: This call caused an error";
        } else if (FAILED_INVALID_PARAMETER_VALUES.equals(wsReturn)) {
            return "Error: Something you gave me was rubbished";
        } else if (FAILED_MISSING_PARAMETER.equals(wsReturn)) {
            return "Error: You left somthing out";
        } else if (FAILED_AUTHENTICATION_FAILURE.equals(wsReturn)) {
            return "Error: Err user name or password was wrong";
        } else if (FAILED_AUTHORISATION_FAILURE.equals(wsReturn)) {
            return "Error: You you can log on, but you dont have rights to do that";
        } else if (FAILED_AUTHENTICATION_EXPIRED.equals(wsReturn)) {
            return "Error: Your logon has expired, sorry";
        } else {
            return null;
        }
    }
}

and I would use it a bit like this

package com.ldc.classes;
import java.util.List;
public class Getaddress {
    public RESTReturn getAddressInJSON() {
        int callStatus = RESTReturn.SUCCESS;
        List<Address> someAddresses = null;
        try {
            someAddresses = doSomthingToGetALoadOfAddress();
        } catch (Exception e) {
            callStatus = RESTReturn.FAILED_GENERAL;
        }
        RESTReturn restReturn = new RESTReturn();
        restReturn.setReturnStatus(callStatus);
        restReturn.setReturnStatusDesc(RESTReturn.statusToString(callStatus));
        restReturn.setPayload(someAddresses);
        return restReturn;
    }
}

so instead of

[]

I would get

{"returnStatus":1,"returnStatusDesc":"Error: This call caused an error", "payload" : "[]"}

which at least tells you that something is not right with the world

Obviously you can get as creative as you want, and a lot depends on how good your internal functions are at displaying their unhappiness, but every little helps and you will make better friends with your client side devs for a bit of consideration like this

Thanks to Ben Poole for pointing out to me that I’m behind the times as normal and this is standard practice, doh!!

Old Comments
————
##### Mark Barton(01/06/2012 14:32:21 GDT)
I wonder though if you should throw a HTTP Status != 200 e.g. 404 along with the custom exception error message.

Its then trivial to catch an error using something like JQuery.
##### Mark(01/06/2012 14:37:24 GDT)
Good point, in this case I have found that this kind of structure is most beloved of the mobile apps lot, who prefer to handle such errors separately due to the someone unreliable nature of mobile networks, but it would be a good idea to use http status items (goes off to look)

New Anime Series- Haiyore Nyariko

First Episode Review for: Haiyore Nyariko

Summary : Well basically all the gods of the Cthulhu Mythos are actually aliens and some of them are good guys (space cops) and are living on earth disguised as cute teenage girls, GOD I LOVE ANIME!!

Animation : A great mix of styles from a acceptable plain cell style to a seriously detailed dark style (hence the 2 screen shots)

Plot Potential: I don’t care if it has a plot (which is Lucky as I cant see any sign of one), as I’m to busy trying to follow all the ‘in jokes’ regarding Lovecraft’s works and RPG’s

Characters: The characters have diddly squat to do with their Lovecraft originals, and this is far more a re skinned “alien girl comes to earth” than anything else

Music: Nothing to speak off, I cant even remember the opening theme and its only 10 mins into the anime!

Reminds me of: To Love-Ru feels just about the same

Overall: I had been really looking forward to a Lovecraft themed anime, and was disappointed when the terrible flash style version Haiyore! Nyaruko-san came out
, this is the anime I was really waiting for and it is very happily received, though I’m sure that a pure lover of H.P. Lovecraft’s works would be rolling in their grave

 

Disclaimer: These are mini reviews of anime’s that are fresh out in Japan and are not licensed in the UK, buy them once they have been licensed or at the very least buy the merchandise, remember if the anime makers make a loss, THEY WILL STOP MAKING ANIME!!

Exposing existing classes for REST top tips

Bolting new functionality onto older systems always has its fair share of fun and games, but exposing internal data structures to external parties is an even greater horror, this does happen though, particularly when clients want to access previously locked down systems via web services or REST interfaces or you want to deliver the same functional via new client eg B2B, mobile etc etc, I have been doing this recently with REST services using the JERSEY library, which like nearly all the good service libraries serialise and deserialise classes for you automatically, however nothing is ever perfect straight out of the box so here are some the things you can do to make your REST services perfect (these work with any JAX/Jackson implementation and often even CXF based systems)

Ill put all the code in first then explain it later (this coded represents the internal class that I am exposing via the services plus the annotations that I have added to it):

package com.ldc.classes;
import java.util.Date;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.codehaus.jackson.annotate.JsonProperty;
public class Address {
    @JsonProperty("referenceId")
    private int Id;
    private Date whenTheyMovedIn;
    private String guessWhenTheyMovedIn;
    private String firstLine;
    private String secondLine;
    private String postCode;
    @JsonSerialize(using = CustomDateSerializer.class)
    public Date getWhenTheyMovedIn() {
        return whenTheyMovedIn;
    }
    public void setWhenTheyMovedIn(Date whenTheyMovedIn) {
        this.whenTheyMovedIn = whenTheyMovedIn;
    }
    @JsonSerialize(using = CustomTextToDateSerializer.class)
    public String getGuessWhenTheyMovedIn() {
        return guessWhenTheyMovedIn;
    }
    public void setGuessWhenTheyMovedIn(String guessWhenTheyMovedIn) {
        this.guessWhenTheyMovedIn = guessWhenTheyMovedIn;
    }
    public String getFirstLine() {
        return firstLine;
    }
    public void setFirstLine(String firstLine) {
        this.firstLine = firstLine;
    }
    public String getSecondLine() {
        return secondLine;
    }
    public void setSecondLine(String secondLine) {
        this.secondLine = secondLine;
    }
    public String getPostCode() {
        return postCode;
    }
    public void setPostCode(String postCode) {
        this.postCode = postCode;
    }
    public int getId() {
        return Id;
    }
    public void setId(int Id) {
        this.Id = Id;
    }
}

package com.ldc.classes;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.SerializerProvider;
public class CustomDateSerializer extends JsonSerializer<Date> {
    @Override
    public void serialize(Date value, JsonGenerator gen, SerializerProvider prov)
            throws IOException, JsonProcessingException {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssz");
        String formattedDate = formatter.format(value);
        gen.writeString(formattedDate);
    }
}

package com.ldc.classes;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.SerializerProvider;
public class CustomTextToDateSerializer extends JsonSerializer<String> {
    @Override
    public void serialize(String value, JsonGenerator gen, SerializerProvider prov)
            throws IOException, JsonProcessingException {
        Date date = null;
        try {
            date = new SimpleDateFormat("MM/dd/yyyy", Locale.US).parse(value);
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }       
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssz");
        String formattedDate = formatter.format(date);
        gen.writeString(formattedDate);
    }
}

Right!, first one is name changes, i.e. you have a field who’s name is just fine in your internal class, but you want to change it when you expose it via REST services (in this case its the “id” field, this was because “id” is a reserved word under iOS which make using it a PITA for the client coders), all you have to do is put the following @annotation and the Alias you want to use just above the field you want to change, and bingo, new name ONLY for REST services

@JsonProperty("referenceId")
    private int Id;

Next is date formatting, the default json date format is not loved by many people I know, and a lot of people prefer ISO 8601, you can use a custom class to do this conversion for you quite easly, again without touching the internal workings of your existing classes, just put this anotation above the ‘getter’ for that field and it will do the conversion for you on the fly (you can see the CustomDateSerializer.class code above)

@JsonSerialize(using = CustomDateSerializer.class)
    public Date getWhenTheyMovedIn() {
        return whenTheyMovedIn;
    }

Finally you can take the custom classes a bit further and change type not just class, for example converting a short form date “DD/MM/YY” stored in a String into a propper Date field. you again just declare a custom class but beef up your code and you can turn anything to anything, funky!

 @JsonSerialize(using = CustomTextToDateSerializer.class)
    public String getGuessWhenTheyMovedIn() {
        return guessWhenTheyMovedIn;
    }

Looking back on this last project and talking with clients about a future one, there is maybe the option of having a dedicated set of classes for external services, far more control and more secure (as, if someone adds a field that really should NOT be exposed it wont automatically flow though to the external service), mind you if you do it that way you will have to weight up the not inconsiderable advantages of speed and easy of maintenance offered by using the internal classes.

but either way these tips might help

Old Comments
————
##### Karsten Lehmann(31/05/2012 15:37:18 GDT)
Nice!
I hope you never try to use this on a Domino server with Extension Library installed. IBM picked Apache Wink as JAX-RS provider and JAX-RS only allows one per JVM (an extremely bad idea).

I did some investigation in this area when we started developing REST APIs for a framework. Somewhere in the JVM, there is a static field that contains the JAX-RS provider and this can only be set one time – with one value.
##### Mark(31/05/2012 18:07:21 GDT)
Karsten: oh poot, hmmmm, there must be a way round that, grrrrrrr

Chris: im off the booze, im on java drugs now
##### chris(31/05/2012 17:46:32 GDT)
dont understand a word of it you must be drinking something stronger than me