Sorting the unsortable

You will have to forgive this blog entry as most of you will know this tip, but it was years since I last used it and when I wanted it last night it completely went out of my head, so I’m putting it up here as an aide memoire

So here is the problem, you have a java collection (in this case a List) containing java custom classes.

List<Address>

and here is the Address class that this is a List of:

package com.ldc.classes;
public class Address {
    private String firstLine;
    private String secondLine;
    private String postCode;
    private int ownerId;
    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 getOwnerId() {
        return ownerId;
    }
    public void setOwnerId(int ownerId) {
        this.ownerId = ownerId;
    }
}

OK, You have got this List of Classes from something that the user has done, and you present them with this List, they then go “cant it be sorted by the Age of the person who lives there” , “errr well not really as the Address class does not contain the residents age, that is in a different class.

package com.ldc.classes;
public class Person {
    private int personId;
    private String firstName;
    private String lastName;
    private int age;  
}

“well just sort it out cant you”……..ffffssssss

Now I expect that most of you are thinking that it would be easier to do this with a SQL statement but believe me there are times when you cant or don’t want to do that, so we have to figure out a way or glue the 2 classes together and making them sortable, we are going to do that with a third class, and one that has a bit of magic in it called “implements Comparable”, our special class need to have the list of address in that we want to sort and something we want to sort them BY (in this case ownerID).

package com.ldc.classes;
public class SortableAddress implements Comparable<SortableAddress> {
    private Address address;
    private int ownerAge;
    public Address getAddress() {
        return address;
    }
    public void setAddress(Address address) {
        this.address = address;
    }
    public int getOwnerAge() {
        return ownerAge;
    }
    public void setOwnerAge(int ownerAge) {
        this.ownerAge = ownerAge;
    }
    public int compareTo(SortableAddress compareForm) {
        int compareAge = ((SortableAddress) compareForm).getOwnerAge(); 
        return this.ownerAge - compareAge;
    }
}

You can see that this class has 2 special bits in it, the first is the “implements Comparable” at the top and the second is the “CompareTo” at the bottom which I have tried to make as simple as possible so you can just swap out your values and get it working on your classes. what this means is you can now use, the standard Collection.sort that you would normally use to sort a list, but use it on your class, here is an example implementing that:

package com.ldc;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.ldc.classes.Address;
import com.ldc.classes.SortableAddress;
public class SortMyClass {
    // OK we have a unsorted list of addresses and we are going to pass them to the function "getasortedListofAddress"
    public List<Address> getasortedListofAddress(
            List<Address> unsortedAddressList) {
        //first lets make a empty sortable address list (our special class)        
        List<SortableAddress> sortableAddressList = new ArrayList<SortableAddress>();
        //and loop though the unsorted list of addresses adding each on to the special class
        for (Address tempAddress : unsortedAddressList) {
            SortableAddress sortableAddress = new SortableAddress();
            sortableAddress.setAddress(tempAddress);
            //here we are getting the owners age which is the value we will be sorting by, to the special class
            sortableAddress.setOwnerAge(getTheOwnersAge(tempAddress
                    .getOwnerId()));
            sortableAddressList.add(sortableAddress);
        }
        //we now have a fully populated class that can be sorted using the standard Collections.sort
        Collections.sort(sortableAddressList);
        //hey presto we have sorted the list
        //now just run though the special class, to move the Address back into their old format, but now they are ordered!!!
        List<Address> listOfSortedAddressToReturn = new ArrayList<Address>();
        for (SortableAddress tempAddress : sortableAddressList) {
            listOfSortedAddressToReturn.add(tempAddress.getAddress());
        }
        return listOfSortedAddressToReturn;
    }
    private int getTheOwnersAge(int ownersID) {
        // some code that gets the owners age from its ID
        int ownersAge = 24;
        return ownersAge;
    }
}

give me a kick if you want me to explain it in more detail, but that that should be enough to provide a practical solution to most of you (and me when I next need it)

Old Comments
————
##### Mark(23/05/2012 14:43:57 GDT)
Oh, I agree generic would be best in real life, I was trying to do the easiest example to follow, but Dear readers Kerr is right when you actually put this bugger into practice
##### Kerr Rainey(23/05/2012 14:24:05 GDT)
I’d try to make this a little more generic by replacing int ownerAge (and associated getters/setters) with Comparable comparable.

Then you push down what it is that the SortableAddress is comparing. Since Integer is Comparable and we have auto boxing, this would be a drop in replacement for what you already have, bar the refactoring of the getter/setter names.

Loader constraint violation on JAVAX webservice (client)

OK, you have done a nice simple Web service client, it runs fine in your tests, you bung it on JBoss and when ever you trigger it you get something like this

java.lang.LinkageError: loader constraint violation: when resolving method “javax.xml.ws.Service.(Ljava/net/URL;Ljavax/xml/namespace/QName;)V” the class loader (instance of org/jboss/classloader/spi/base/BaseClassLoader) of the current class, com/sun/j2ee/blueprints/opc/powebservice/XYZService, and the class loader (instance of ) for resolved class, javax/xml/ws/Service, have different Class objects for the type javax/xml/namespace/QName used in the signature

You might miss the “loader constraint violation” part and think that its to do with the QName, or that your @WebServiceRef annotation is not working, well don’t bother, you have a clashing .Jar library, and its most likely going to be “stax-api” (which Jboss loads before you even get there with your app), so you will want to looking in your Lib directory ( which will be in the “WEB-INF” directory in your war file or build target directory ) of your packaged app to see if the little devil is in there, if you’re dealing with your libs manually then you are going to just have to remember why you put it there (although http://www.findjar.com/ can be a lot of help there), if you are using maven then the following command will tell what jar’s come from which libs

mvn dependency:tree

This gives you the following kind of display

[INFO] [dependency:tree {execution: default-cli}]
[INFO] com.firstbest:fbs-mobile-proxy:war:0.1
[INFO] +- asm:asm:jar:3.3:compile
[INFO] +- org.apache.ant:ant:jar:1.7.0:compile
[INFO] '  - org.apache.ant:ant-launcher:jar:1.7.0:compile
[INFO] +- com.sun.jersey:jersey-servlet:jar:1.12:compile
[INFO] '  - com.sun.jersey:jersey-server:jar:1.12:compile
[INFO] +- com.sun.jersey:jersey-json:jar:1.12:compile
[INFO] '  +- org.codehaus.jettison:jettison:jar:1.1:compile
[INFO] '  '  - stax:stax-api:jar:1.0.1:compile
[INFO] '  +- com.sun.xml.bind:jaxb-impl:jar:2.1.12:compile (version managed from
 2.2.3-1)
[INFO] '  '  - javax.xml.bind:jaxb-api:jar:2.1:compile
[INFO] '  '     - javax.activation:activation:jar:1.1:compile
[INFO] '  +- org.codehaus.jackson:jackson-core-asl:jar:1.9.2:compile
[INFO] '  +- org.codehaus.jackson:jackson-mapper-asl:jar:1.9.2:compile
[INFO] '  +- org.codehaus.jackson:jackson-jaxrs:jar:1.9.2:compile
[INFO] '  +- org.codehaus.jackson:jackson-xc:jar:1.9.2:compile
[INFO] '  - com.sun.jersey:jersey-core:jar:1.12:compile
[INFO] +- log4j:log4j:jar:1.2.16:compile
[INFO] +- junit:junit:jar:4.10:test
[INFO] '  - org.hamcrest:hamcrest-core:jar:1.1:test
[INFO] +- taglibs:standard:jar:1.1.2:compile
[INFO] +- org.apache.ws.commons:ws-commons-util:jar:1.0.1:compile
[INFO] '  - xml-apis:xml-apis:jar:2.0.2:compile (version managed from 1.0.b2)
[INFO] - org.apache.neethi:neethi:jar:3.0.1:compile
[INFO]    +- wsdl4j:wsdl4j:jar:1.6.2:compile
[INFO]    - org.codehaus.woodstox:woodstox-core-asl:jar:4.0.8:compile
[INFO]       - org.codehaus.woodstox:stax2-api:jar:3.0.2:compile

You will now need to put in exclusions in your pom.xml to stop the jars that you don’t want from being loaded in, here is an example

<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-servlet</artifactId>
    <version>1.12</version>
    <exclusions>
        <exclusion>
            <artifactId>stax-api</artifactId>
            <groupId>javax.xml.stream</groupId>
        </exclusion>
    </exclusions>
</dependency>

You might have to add a number of these and check the dependency:tree each time to make sure another does not pop in, in order to get them all.

This SHOULD fix your problem, but sometimes you either want your version of the Jar file to be on the server or you simply cant seem to get rid of a jar field in your build, you can tell jboss to use your jars over its own one by adding a jboss-classloading.xml file in src/main/webapp/WEB-INF directory. and adding the following lines to it.

<?xml version="1.0" encoding="UTF-8"?>
<classloading xmlns="urn:jboss:classloading:1.0"
              export-all="NON_EMPTY"
              import-all="true"
              parent-first="false">
</classloading>

That should sort it out.

Old Comments
————

##### Ben Poole(23/04/2012 23:11:54 GDT)
This sort of shyte is why we love Java so.

No. Really.

##### Mark Myers(12/05/2012 13:23:16 GDT)
tell me about it

Mint 12 and Cinnamon

I really enjoyed using Mint Linux 11 and was pleased when mint 12 came out, but had not quite got round to installing it since it came out, partially due to the fact that mint uses the backup and restore method of upgrading (which I never seem to have time to do*) and partly due to the fact mint 11 works just right for me

Anyway with far to much work to do on a weekend I decided it was the perfect time to upgrade my laptop (sigh!) so off I went.

The ISO to boot disk went as normal even though mint now provide a hybrid ISO option (see here though this page may expire soon), I just used unetbootin.

The install and configuration was exceptionally easy and I was very gratified that the first things mint tried to do were install suitable hardware drivers (a quirk of linux) and install software updates and patches, exactly what I wanted to do, all things looked ok and all services seemed just fine, so on to restoring my personal settings.

This was also my first time using the full mint upgrade, in that you do a backup, wipe the disk for a fresh install then restore the backup which also installs any software you might have had on before.

You have 2 forms of backup/restore:

Software: This is just the list of software you have on your system fed to the package installer,so obviously it does not restore customs packages you have installed (such as vmware and other purchased products) it does however tell you which ones it has not been able to restore. this worked just perfectly.

User data: This backups/restores basically your home directory (which is everything in a Linux installation) now I have been backing up to a basic tar ball ( the lowest compression of the 3 archive “zip” formats the Mint backup utility supports) which backed up the 200Gb that is my home directory fairly quickly, but good grief who wrote the de-compression gui, I started it running in the evening and next day in was just 20% of the way though the files, I stopped it and did a Command line “tar” and it worked out about 10 to 15 times faster, now I know GUI’s add an over head, but really lads! , now part of this is my fault as the backup utility’s default setting is not to use any compression at all and just copies all the user data to a separate place, in hind sight I should have done that for this kind of thing.

Now to start with I thought that mint had gone back to the standard Gnome 2 bar layout as that was what I was looking at, but this turns out to be just what they have been forced back to during the movement away from Gnome 2, what they have up their sleeve is Cinnamon, which is a reurn to their single bar desktop (which I have now go used to) I am dreadfully torn on this new desktop, it has so much to offer and feels and looks so good but it is still very new and has the odd quirk, thankfully the mint guys let you swap which desktop you use at the login screen,

Now this swapping has turned out to be a must have feature, as Cinnamon is really really unhappy when faced with multiple monitors (powered by nvinda restricted drivers), no menu bars at all, no functionality, just a mouse pointer and hot keys, ICK!! (I suppose I should really register it as a bug, but in the mean time they have still included MATE so I swap back to that when I have 2 monitors on, even this has its ups and downs, you don’t need to do the script fix to get your menu bars back anymore but do need to screw about with your fonts as a load of the standard gnome 2 themes are missing,

I’m also having odd UI issues on all systems on this build, such as inconsistent mouse clicks near the screen edges/function hot zones Edit this turns out to be due to my habit of flicking my mouse cursor out the way when I enter a browser bar End Edit*, repeat keys not working and some hardware buttons sulking, but frankly that is to be expected as its only just out, these people have done an amazing job and all in all I am very pleased, all applications work fine, it is beautiful and very very stable, so I have done my donation for my “licence” (as I see it), as I genuinely see mint as good solid usable distro and worth my support.

yes yes I do use incremental backups using jungledisk

** For reference if the mint boys want to recreate the issue, im backed up to a external WD 2.5 inch USB3 hdd and my machine is a Thinkpad W510 with 2 x 500GB seagate hybrid drives and 16Gig of memeory running the PAE core

VMware image of Laptop Tips and Gotchas

Recently I started working for a client that has a good enlightened approach to equipment, they provided me with an excellent laptop, but had no objection to me using my 16gig/1tb+/i7 monster, so I set about making a vmware image, this was hampered by their reasonable security setup and some oddities of the way that vmware converts hard drives. here’s what I leaned from the process

Problem: 0000007B error on boot
Solutiuon: This is caused by a variety of problems but always boils down to not being able to get access to the boot drive, I’m not going to go into the different reasons, but the best fix is to use a SCSI controller on your virtual machine, first step is to make sure that you convert the machines disk to SCSI, by default when running the VMWARE converter the “disk controller” setting (on the option screen, under devices) it is set to “auto select” which never seemed to work for me, so i set it to SCSI, as shown below

Now this means that you have to have a SCSI driver installed and working on your machine, thankfully this is already installed on Vista and windows 7, but NOT turned on, vmware say “set your SCSI drivers the same as a machine that already works” which is an dumb arse thing to say if you dont give an example, so here are the settings that work.

they are found in the registry at

HKEY_LOCAL_MACHINE -> SYSTEM -> ControlSet001 -> services

now you can reconvert you vmware machine and have no problems

NOTE: If you have already done the conversion and DONT have access to the source machine any more (ignoring the fact your a twit for not testing the VMWARE image before losing access) go here as this is the best writeup of a fix i have seen so far, it did not work for me as do to the problem converter setting problem i mentioned above, but it will fix the problem most of the time

Problem: Symantec Endpoint Encryption
Solution: On a machine with this program installed you have to somehow get round it as it is incompatable with VMWARE, thankfully in this case i had a power user level account (meaning i could install and unistall software) but not decrypt the laptop i wanted to clone (nore should i as it was not my hardware), Sooo, just run the conversion software, and on the first boot, all will seem ok and the HDD will be unencrypted, BUT, the symatic service will notice this little horror and on you next reboot will intercept the boot and ask for a password, attempt to encrypt the virtual HDD then procede to hang and sulk.

simple solution, as soon as you have booted the first time, uninstall the Endpoint Encryption service, this will bypass the symatic software security, as your hdd is currently still unencrypted you don’t need the rights to decrypt it, and your booting will continue as normal

NOTE: I store my VMWARE machines on an encrypted HDD in my laptop, so i felt this was an acceptable action as i would not be lowering the security level of clients data, had this not been the case, I would not have performed this action, remember the old saying “Do NOT screw with your clients data lest you be kicked in the balls and shot in the back of the head in a dark alley”

Restart Linux xserver hotkey

I cant believe I have lasted this long not knowing this, but there is a hot key combination to restart the xserver without the command line or a computer restart (doh!) on Ubuntu derived distros.. useful for when you make multi screen property changes (windows and mac scum may laugh at this point if they wish)

Ctrl+Alt+”Backspace”

Careful as it closes all existing apps.

Old Comments

Ben Poole(23/12/2011 14:55:18 GMT)

Chortle.

Ben Poole(23/12/2011 14:54:50 GMT)

Snigger.

Ben Poole(24/12/2011 22:01:33 GMT)

GUFFAW!

Mark Myers(25/12/2011 23:18:16 GMT)

@ben well you match the criteria of both mac and scum