Posted by & filed under Java.

Jammer is a quick 1hr project that clones IRC discussion on Yammer.

Yammer is a social network for internal use by organisations. It’s a great way to broadcast information and have asynchronous discussion, and simple enough for anyone to use.

Developers already have a great forum for asynchronous discussion – IRC. IRC is great for developers to use, but most irc client software is not particularly user friendly. Unless you idle in the channel all the time you will miss scrollback.

I haven’t used Yammer for some time so I thought I’d remind myself how to use the API by building a bridge between IRC and Yammer. Here’s the result of just over an hour’s work:

Jammer is a quick proof of concept IRC bot that will sit in an IRC channel and clone messages from authorised users to a specified group in Yammer. It lets you keep a record and publish discussion for others in the organisation to see.

The code is on github at https://github.com/benjiman/jammer

It might be useful to someone else as a tutorial for getting started with the Yammer API and how to authenticate with oauth. There are only 3 short Java files.

Jammer

Here’s how you run Jammer:

 $ git clone https://github.com/benjiman/jammer.github
 $ cd jammer
 $ mvn compile
 $ mvn assembly:single
 $ java -jar ./target/jammer-0.0.1-SNAPSHOT-jar-with-dependencies.jar <irc server (in quotes)> <channel> <yammer group id> <yammer client id> <yammer client secret>

Then in your IRC client:

 /msg jammer auth

Click the link provided, approve the app, and copy the authentication token back with

 /msg jammer auth <token>

Now simply join the channel the bot is in and start talking and all messages will be cross-posted to Yammer.

You can get a client id and client secret in Yammer by registering a new application.

You can get a group id by visiting the group on Yammer.com and copying the id at the end of the URL

For more information read

The Yammer API documentation
There’s a tutorial for PircBot (Easily write IRC bots in Java)

Posted by & filed under Java.

Hibernate is great, but often one has to specify queries as HQL in Strings, or as criteria which allow building of invalid queries.

It would be great to use the java type system to help enforce correct queries. I am aware of some tools to do this, but all the ones I have seen require either a code generation step, or preclude the use of standard getters/setters.

Here is a proof of concept of one approach that I think could work. It allows things like:

    public List<Person> getPeopleByName(final String firstName, final String lastName) {
        return new Query<Person>() {
            public CompletedQuery spec(Person person) { // <- Only Person can be passed to here.
                return where(person.getFirstname())
                    .equalTo(firstName) // <- Only comparisons are valid at this step, a .and(... would be a compilefailure.
                    .and(person.getLastname())
                    .equalTo(lastName)
                    .select(); // <- Omitting this would be a compile failure due to return type.
            }
        }.list(HibernateUtil.getSessionFactory().getCurrentSession()); // <- Method returns a List<Person>
    }

A toString on the above Query<Person> when passed firstname benji and lastname weber would yield:

FROM Person WHERE firstname = 'benji' AND lastname = 'weber'

If we were to try to supply a non-string value for first name we would get a compile failure.

    public List<Person> getPeopleByName(final String firstName, final String lastName) {
        return new Query<Person>() {
            public CompletedQuery spec(Person person) {
                return where(person.getFirstname())
                    .equalTo(firstName)
                    .and(person.getLastname())
                    .equalTo(5) // <- Compile failure
                    .select();
            }
        }.list(HibernateUtil.getSessionFactory().getCurrentSession());
    }

This approach can even work querying through relationships

    public List<Person> getPeopleByAddress(final Address address) {
        return new Query<Person>() {
            public CompletedQuery spec(Person person) {
                return where(person.getAddress().getId())
                    .equalTo(address.getId()) // < - Only Integers are allowed here.
                    .select();
            }
        }.list(HibernateUtil.getSessionFactory().getCurrentSession());
    }

A toString on the above Query<Person> when passed an Address with id 2 would yield:

FROM Person WHERE address.id = 2

To implement this I used a few tricks:

  • Query<T> is an abstract class that uses Gafter’s Gadget to obtain a Class<T> this is used to get the entity name that we are querying, and later to create an instance.
  • A Dynamic Proxy class is created for this Class and passed to the spec(T value) method.
  • This dynamic proxy records all calls made to it. If the call is to a method that returns another mockable object (e.g. getAddress() in the above example) then another recording-proxy is returned.
  • The query builder then uses the recorded method calls to determine which properties are being queried
  • The need to return a CompletedQuery interface forces the implementor to type a complete query or they will get a compile failure.
  • Interfaces represent the valid progressions at each step of the query building. e.g. after a where() you need to supply a comparison equalTo(), or like() etc. After a comparison you can complete the query or add another restriction with and();

Here is the example implementation of Query that enables this. Full demo code here

package uk.co.benjiweber.typesafehibernate.typesafe;
 
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.hibernate.Session;
import org.springframework.util.StringUtils;
 
public abstract class Query<T> {
 
    private final Type type;
    private final Recorder<T> recorder;
    private final StringBuilder queryBuilder = new StringBuilder();
 
    public Query() {
        Type superclass = getClass().getGenericSuperclass();
        this.type = ((ParameterizedType) superclass).getActualTypeArguments()[0];
        this.queryBuilder.append("FROM " + getParamClass().getSimpleName());
        recorder = createMockInstance();
        spec(recorder.getObject());
    }
 
    public abstract CompletedQuery spec(T entity);
 
    public interface CompletedQuery {
    }
 
    public <U> Comparison<U> where(U ignore) {
        queryBuilder.append(" WHERE ");
        return comparison(ignore);
    }
 
    private <U> Comparison<U> comparison(U ignore) {
        return new Comparison<U>()  {
 
            public QueryOptions equalTo(U value) {
                return comparison(value, "=");
            }
 
            public QueryOptions notEqualTo(U value) {
                return comparison(value, "!=");
            }
 
            public QueryOptions like(U value) {
                return comparison(value, "LIKE");
            }
 
            private QueryOptions comparison(U value, String operator) {
                boolean quote = value != null && String.class.equals(value.getClass());
 
                queryBuilder.append(recorder.getCurrentPropertyName()).append(" ").append(operator).append(" ").append(quote ? "'" : "").append(value).append(quote ? "'" : "");
                return new AbstractQueryOptions()  {
 
                    public <V> Comparison<V> and(V o) {
                        return Query.this.and(o);
                    }
                };
            }
        };
    }
 
    private <U> Comparison<U> and(U ignore) {
        queryBuilder.append(" AND ");
        return comparison(ignore);
    }
 
    public interface Comparison<U> {
 
        QueryOptions equalTo(U value);
 
        QueryOptions notEqualTo(U value);
 
        QueryOptions like(U value);
    }
 
    abstract static class AbstractQueryOptions implements QueryOptions {
 
        public CompletedQuery select() {
            return new CompletedQuery()  {
            };
        }
    }
 
    public interface QueryOptions {
 
        <V> Comparison<V> and(V o);
 
        CompletedQuery select();
    }
 
    private Recorder<T> createMockInstance() {
        Class<T> cls = getParamClass();
 
        return RecordingObject.create(cls);
    }
 
    private Class<T> getParamClass() {
        return type instanceof Class<?>
                ? (Class<T>) type
                : (Class<T>) ((ParameterizedType) type).getRawType();
 
    }
 
    @Override
    public String toString() {
        return queryBuilder.toString();
    }
 
    public List<T> list(Session session) {
        return session.createQuery(toString()).list();
    }
}
 
class Recorder<T> {
 
    private T t;
    private RecordingObject recorder;
 
    public Recorder(T t, RecordingObject recorder) {
        this.t = t;
        this.recorder = recorder;
    }
 
    public String getCurrentPropertyName() {
        return recorder.getCurrentPropertyName();
    }
 
    public T getObject() {
        return t;
    }
}
 
class RecordingObject implements MethodInterceptor {
 
    private String currentPropertyName = "";
    private Recorder<?> currentMock = null;
 
    @SuppressWarnings("unchecked")
    public static <T> Recorder<T> create(Class<T> cls) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(cls);
        final RecordingObject recordingObject = new RecordingObject();
 
        enhancer.setCallback(recordingObject);
        return new Recorder((T) enhancer.create(), recordingObject);
    }
 
    public Object intercept(Object o, Method method, Object[] os, MethodProxy mp) throws Throwable {
        if (method.getName().equals("getCurrentPropertyName")) {
            return getCurrentPropertyName();
        }
        currentPropertyName = StringUtils.uncapitalize(method.getName().replaceAll("^get", ""));
        try {
            currentMock = create(method.getReturnType()); //method.invoke(o, os);
            return currentMock.getObject();
        } catch (IllegalArgumentException e) {
            //non-mockable
            return null;
        }
    }
 
    public String getCurrentPropertyName() {
        return currentPropertyName + (currentMock == null ? "" : ("." + currentMock.getCurrentPropertyName()));
    }
}

Posted by & filed under Java, Uncategorized.

One annoyance in Java is having to do instanceof checks on multiple lines. e.g.

if (object instanceof Foo) {
    Foo foo = (Foo)object;
    foo.foo();
}

While this is often a sign of a design failure, there are times when instanceof checks are required often due to framework constraints etc. The above is quite ugly and involves using 3 lines instead of 1 for a single method call. If foo() is a void method we can’t even use the ternary ? : operator to make it more concise.

In c# with Lambdas and Extension methods one can create something like :

    object.When<Foo>(foo => foo.Foo());

Where “When” is an extension method added to all objects which takes a type parameter and a lambda to execute if the type parameter matches. (Implementation available if anyone cares).

Since Java doesn’t have Extension methods or Lambdas yet (Oracle minus minus) we can’t do this. We can however always use reflection and get something like:

package scratchpad;
 
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
 
import static scratchpad.When.when;
 
public class Let {
	public static void main(String... args) {
		Object a = new Foo();
		Object b = "hello world";
 
		when(Foo.class).isTypeOf(a).foo(); // Prints "foo"
		when(Foo.class).isTypeOf(b).foo(); // Does nothing at all
	}
}
 
class Foo {
	public void foo() {
		System.out.println("foo");
	}
}
 
class When {
	public static <T> Is<T> when(final Class<T> cls) {
		return new Is<T>() {
			@SuppressWarnings("unchecked")
			public T isTypeOf(Object o) {
				return o != null && cls.isAssignableFrom(o.getClass()) 
					? (T)o
					: NullObject.create(cls);
			}
 
		};
	}
 
	public interface Is<T> {
		public T isTypeOf(Object o);
	}
}
 
class NullObject implements MethodInterceptor  {
 
	@SuppressWarnings("unchecked")
	public static <T> T create(Class<T> cls){
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(cls);
		enhancer.setCallback(new NullObject());
		return (T)enhancer.create();
	}
 
	public Object intercept(Object o, Method method, Object[] os, MethodProxy mp) throws Throwable {
		return null;
	}
}

Posted by & filed under Uncategorized.

I meant to post some time ago about how great the n900 is for java development. Not only can one install OpenJDK, but Netbeans is even usable. It’s pretty easy to get running. Just install openjdk6 in the application manager. Then download and run the netbeans installer.

installation

running

It even runs at quite a reasonable speed if you’re not running much else.

Posted by & filed under Uncategorized.

Normally a command-line Java application will have an entry method that looks something like:

public static void main(String... args) {
    /* Code that launches the application/deals with command line params here */
}

This is far too easy, there must be a way to NIH it ¬_¬. There are a few annoyances with the public static void main method.

  • Args are passed in as an Array, rather than something like a List<String>
  • We can’t choose to call the main method something other than main.
  • It’s a bit obscure how the startup process works.

There is a common way to execute code on app startup without using a static void main method. You can use a static initialization block:

static {
    /* Code here run on class load. */
}

So we could launch our application from within a static initialization block. However this presents a number of problems:

  1. We get a nasty error when the application finishes (Exception in thread “main” java.lang.NoSuchMethodError: main)
  2. We have no access to the command line arguments
  3. We can’t have multiple “Main” classes with this method (Both static initialization blocks will be run, if both classes are loaded)
  4. It doesn’t really provide any benefits over static void main.

These problems can, however, all be overcome.

Suppressing NoSuchMethodError

We can just call System.err.close(); at the end of our initialization method.

Access to the command line arguments

This one is probably the most difficult. I’ve not found any “good” way to do this, but there is a hack that works at present on Sun’s Java, though it may stop working at any point.

sun.misc.VMSupport.getAgentProperties().get("sun.java.command")

This will give the command line string used to start the application. There are alternatives involving attaching to the currently running VM with the Agent API or shelling out to external processes and using platform-specific commands to work out the command used to start the application. If anyone knows a proper way to access the command line arguments using the public API then please let me know.

Multiple Main Classes

We need to get our initialization system to ignore invocations from classes other than the one used to start our application. This can be done by checking the length of the StackTrace. e.g.

new Throwable().fillInStackTrace().getStackTrace().length == 2;

Reflection Examples

With these 3 issues solved it’s possible to do things like:

package MainlessDemo;
 
import java.util.List;
import static uk.co.benjiweber.realjava.mainless.Bootstrap.init;
 
public class ReflectionMainless {
	static { init(); }
	public void main(final List<String> args) {
		System.out.println("Hello World");
		System.err.println("From std err");
		for (String arg : args) {
			System.out.println(arg);	
		}
	}
}
/* Output:
$ javac -cp .:./RealJava.jar ./MainlessDemo/*.java && java -cp .:./RealJava.jar MainlessDemo.ReflectionMainless Foo Bar Baz
Hello World
From std err
Foo
Bar
Baz
*/

Here a statically imported “init” method instantiates our main class, invokes our non-static main method, and passes it the command line arguments. The class to instantiate can be determined by walking back up the stack trace again.

We can also inject constructor arguments if we wish:

package MainlessDemo;
 
import java.util.List;
import static uk.co.benjiweber.realjava.mainless.Bootstrap.init;
 
public class ReflectionMainlessWithArgs {
 
	// This time we pass in the constructor argument
	static { init("Hello World"); }
 
	private final String message;
 
	// Even though we load another class that is Launchable it doesn't get launched.
	static final ReflectionMainless test = new ReflectionMainless(); 
 
	public ReflectionMainlessWithArgs(final String message) {
		this.message = message;
	}
 
	public void main(final List<String> args) {
		System.out.println(message + " (Passed in through constructor)");
		for (String arg : args) {
			System.out.println(arg);	
		}
	}
}
/* Output:
$ javac -cp .:./RealJava.jar ./MainlessDemo/*.java && java -cp .:./RealJava.jar MainlessDemo.ReflectionMainlessWithArgs Foo Bar Baz
Hello World (Passed in through constructor)
Foo
Bar
Baz
 
*/

Interface Examples

Unfortunately, apart from substituting an argument Array for a List, we ‘ve not really improved anything. However, now that we’re in control of the initialization process we can do more interesting things, like use an interface:

public interface Launchable {
	public void main(List<String> args);
}
package MainlessDemo;
 
import java.util.List;
import uk.co.benjiweber.realjava.mainless.Launchable;
import static uk.co.benjiweber.realjava.mainless.Bootstrap.init;
 
public class SaferMainless implements Launchable {
	static { init(new SaferMainless()); }
 
	public void main(final List<String> args) {
		System.out.println("Hello from a Launchable");
		for (String arg : args) {
			System.out.println(arg);	
		}
	}
}
 
/*
Output:
$ javac -cp .:./RealJava.jar ./MainlessDemo/*.java && java -cp .:./RealJava.jar MainlessDemo.SaferMainless Foo Bar Baz
Hello from a Launchable
Foo
Bar
Baz
*/

Now it’s clearer how the initialization process works, you can use your IDE to follow execution through from the init block to the main method. This also gives us the freedom to call our main method something different, and inject dependencies before reaching the main method.

package MainlessDemo;
 
import java.util.List;
import uk.co.benjiweber.realjava.mainless.Launchable;
import static uk.co.benjiweber.realjava.mainless.Bootstrap.init;
 
public class SaferAnonymousMainless {
 
	static { init(new Launchable() {
		public void main(final List<String> args) {
			SaferAnonymousMainless mainless = new SaferAnonymousMainless();
			mainless.setMessage("I was injected manually");
			mainless.someMethodNotCalledMain(args);
		}
	}); }
 
	private String message;
 
	public void setMessage(final String message) {
		this.message = message;
	}
 
	public void someMethodNotCalledMain(final List<String> args) {
		System.out.println(message);
		for (String arg : args) {
			System.out.println(arg);	
		}
	}
}
/* 
Output:
$ javac -cp .:./RealJava.jar ./MainlessDemo/*.java && java -cp .:./RealJava.jar MainlessDemo.SaferAnonymousMainless Foo Bar Baz
I was injected manually
Foo
Bar
Baz
 
*/

Source for the BootStrap.init method is here

Thanks to Faux for some of the ideas.

Yes I know this isn’t remotely a good idea, no need to tell me 🙂

Posted by & filed under openSUSE.

Here are my notes from the software portal talk Pascal and I gave yesterday at the openSUSE conference.

The slides we used are also available.

What is the Software Portal?

Software Portal is a free-software web-application that runs as a service on on opensuse-community.org. It provides both a web-ui and an API. It is possible you are already using the software portal if you use the webpin search page or the command line webpin programme written by Pascal. For the last few months this has been backing on to the software portal.

The software portal indexes package repositories, both those discoverable with the openSUSE build service API and those users add manually through the web interface. It also allows users to contribute additional metadata such as ratings, comments, tags, and screenshots. These two sources of information are both associated against “applications”. The web user-interface is primarily a way of finding, installing, and adding information about applications.

Applications

So, what is an application? We define applications within software portal to be a higher level concept than packages. Applications are what users perceive software as – A product they are looking for and may wish to install to perform a task. Packages are the mechanism of how applications are distributed to users. Packages are platform-specific, they require different packages for different operating systems, and different architectures. The split between packages is also defined by pragmatic issues related to distribution more than conceptual boundaries. Some applications may require multiple packages installed in order to use. Conversely some packages contain more than one application. For example the application GIMP on openSUSE on a 32bit platform might consist of the main gimp package, a gimp-banding package, and some core plugins in another package. Another opposite example is the kdenetwork3 package that contains multiple chat applications.

The web-ui provides application-level search, tag-browsing, and installation.

In the software portal we strive to map packages to the appropriate applications. There are three mechanisms we currently use to do this:

  1. A set of rules stored in the database that map common package naming conventions to application names.
  2. For example: currently kde4 applications tend to have the packagename kde4-packagename. Many non-desktop specific packages start with the application name. Rules are assigned priorities so that more-specific rules can override general rules.

  3. The presence of .desktop files in packages.
  4. User-defined mappings.
  5. Through the web-ui, users can define additional applications and edit existing applications. While editing, users can define rules for which source-packages should be mapped to which applications during repository indexing.

One of the main aims of abstracting away from packages to applications is that we want to allow users to just click install at an application level, without having to know what their hardware/software platform is or choose which package vendor to use. To this end we need some way to choose a preferred vendor for each application in the case where there are multiple vendors of that application. We do this by

  1. Associating a priority with repositories based upon their support status and stable/experimental status.
  2. So the highest priority would be the update and static distribution repositories, and the lowest would be random home: repositories in the openSUSE build service.

  3. Allowing power-users to customise the preferred vendor and selection of binary packages to install by default for an application. Via the web-ui.

The operating system agnosticism is provided by one-click-install and the system package management can choose the appropriate architecture packages.

Why is it needed?

openSUSE embraces third party vendors of packages. Which means that there’s a low barrier to entry and anyone can start packaging and publishing software to users. However, this freedom leads to a confusing situation for users.

Many repositories

(Software Portal is currently indexing around 4000 and this is not exhaustive.)

Package duplication.

Some applications such as amarok has been packaged dozens of times for openSUSE by different people for various reasons. In this case how does a user choose which vendor to choose? We also encourage duplication by not making it easy to find existing packages.

Lack of user-feedback

One packager may package dozens of packages but may not extensively use many of them. We’re not currently good at collecting feedback of package and software quality from users. It’s also not clear for users where to file bugs for the software they’ve just installed.

Confusing concepts

It should not be necessary for users to understand concepts such as packages and package repositories just to install software. It’s also unnecessary for users to know what operating system (version) they’re running or on what hardware.

Insufficient data

We currently rely heavily upon a few package maintainers to source and supply metadata for packages. Packages come with descriptions and summaries but lack more rich metadata such as screenshots. There are many more end users than packagers so it makes sense to let them contribute this information.

Implementation Platform

Software portal project is implemented using Java 6, making heavy use of Spring Framework, Apache Wicket, Jersey, Maven, and MySQL.

Future Plans

We are currently working on finalising a “1.0” release, fixing some of the major bugs, performance issues, and polishing the user interface to get to the point that it is safe for end users to start using and we can publicise it. We need help right now in testing and finding bugs.

The biggest performance issues I am currently working on are:

  • Search of all 20+ million unique file names every time someone performs a search.
  • Calculation of the best binary packages to install for applications with dozens of different vendors.

Challenges arise from the frequency of change of the package repositories (thousands of packages may change every day). Index formats are a balance between query performance and update performance.

After first release one of the biggest issues we want to resolve is that people cannot use their existing login that they use for all other openSUSE services to log into the software portal. Due to Novell control of the authentication system. We have a dependency on Novell here, but hope to implement openID support and that Novell will be able to implement an openID provider.

Further ahead we would like to work on things like:

A recommendation engine

We could do things like recommend you plugins for software you have installed.

User-specific search.

When we know information about the user, their preferences, and what operating system they have installed we can tailor search results to match them, prioritise applications that are available for their platform, and give higher priority to applications for their preferred desktop.

Translation

The web-ui is already translatable. Application descriptions are stored in a translatable manner but the source of this information (package repositories) generally does not have translations. We could potentially build an interface to allow people to translate the content itself if there were a demand for it.

Use Build-Service remoting or Hermes notification framework

Move towards a push model where the software portal is notified of new software, rather than the current pull system where we have to poll package repositories to see if they’re changed, then compute the differences from the previous version if they have.

Integration with bugzilla

Report bugs directly from software portal.

Integration with upstream

Perhaps via the DOAP (Description of a Project) format. We could both consume DOAP files provided by upstream projects, and expose DOAP for software we have indexed.

The Master Plan

Our original aim was to supplement the web-service with a rich desktop client that utilises the information indexed by the software portal and combines that with information available to it as an application running on the local system, such as the currently installed packages, and the repositories the user subscribes to.

Perhaps a YaST module? We already have a package-search yast module that does use the software-portal API to search for packages, but much more powerful things are possible. Unfortunately we do not currently have the time to work on a desktop client on top of the web app itself so if anyone is interested in working on this side of things please get in touch.

Demo

We gave a demonstration of some of the features mentioned above during our talk. You can play with the current version online. Though please be aware there are lots of known bugs and performance issues, it’s not ready for end-users yet.

That said, please do play with it, and let us know what’s broken by filing bugs under the openSUSE.org->Software Portal bug component.

If you want to try out more of the administrator features such as adding repositories, adding applications, customising package to application mapping etc then create an account and drop me an email so I can grant you permissions.

How can you help?

  • Start testing it
  • File bug reports
  • Help create and organise content
  • Developers who know Java and want to contribute code would be welcome. We would be happy to help people get started with the codebase.
  • Designers can help us improve the look and feel and interaction. Some of the processes such as mapping packages to applications are somewhat klunky. It would be good to get some suggestions on how to make this functionality easier to use.

Posted by & filed under Holiday.

I got back this week from holiday cycling and walking in Switzerland. I cycled down from Basel in the north via Bern and Interlaken to Fiescheralp. Then back via Luzern and Zürich.

Fiescheralp is next to the beautiful Aletsch Glacier

Aletsch Glacier

I stayed in a chalet here for a few days with family and did some climbing and walking

Eggishorn to Bettmerhorn

Eggishorn to Bettmerhorn

The highlight of the trip was cycling through the mountains. Especially Grimselpass.

 

GrimselPass from Gletch

GrimselPass From Gletch

GrimselPass Towards Meiringen

GrimselPass Towards Meiringen

Brienz

Brienz

Brunigpass

Brunigpass

Posted by & filed under Java.

Here’s a sillier one from last night…

People often complain about not being able to return multiple values from a method in Java. I can’t see a good reason for wanting to do this, but some do.

The example I was given was wanting to do:

int foo, bar, baz; list(foo, bar, bar) = func(ponies);

Where func(ponies) returns 3 values which are then assigned to the local variables foo, bar, and baz.

There are plenty of sensible ways of achieving this, but what if we’re trying to get as close as possible to the above method? We can only return one thing from a method, but that could be a chain. We also can’t modify the local foo,bar,baz from inside the list method, but we could if we wrap them in references.

If we abuse the fact that currency characters are valid identifiers in Java, for the ultimate in unreadability; We can use $(x,y) to be a pair of x and y, $$ to terminate a list, and £(x) to either reference or dereference x.

Then we can do something like this ¬_¬

/** OUTPUT
Foo = 1
Bar = 2
Bingo = Badgers
Baz = 3
**/
 
package scratchpad;
 
import static scratchpad.$.$;
import static scratchpad.$$.$$;
import static scratchpad.$.expand;
import static scratchpad.£.£;
 
public class MultipleReturn
{
	public static void main(String... args)
	{
		new MultipleReturn().demo();
	}
 
	public void demo()
	{
		£<Integer> foo = £(-1), bar = £(-1), baz = £(-1);
		£<String> bingo = £("");
 
		expand(foo()).into(foo,bar,bingo,baz);
 
		System.out.println("Foo = " + £(foo));
		System.out.println("Bar = " + £(bar));
		System.out.println("Bingo = " + £(bingo));
		System.out.println("Baz = " + £(baz));
	}
 
	public $<Integer,$<Integer,$<String,$<Integer,$$>>>> foo()
	{
		return $(1,$(2,$("Badgers",$(3,$$))));
	}
}
 
interface Tuple {}
 
class $$ implements Tuple
{
	private $$() { }
	public static $$ $$ = new $$();
}
 
class $<T,U extends Tuple> implements Tuple
{
	public T _1;
	public U _2;
 
	protected $(T t,U u)
	{
		this._1 = t;
		this._2 = u;
	}
 
	public static <T> $<T,$$> $(T t)
	{
		return new $<T,$$>(t,$$);
	}
 
	public static <T,U extends Tuple> $<T,U> $(T t, U u)
	{
		return new $<T,U>(t,u);
	}
 
	public interface Expander
	{
		public void into(£... refs);
	}
 
	public static Expander expand(final $<?,? extends Tuple> vals)
	{
		return new Expander()
		{
			public void into(scratchpad.£... refs)
			{
				if (refs.length < 1)
					return;
 
				$ current = vals;
				refs[0]._1 = current._1;
				if (current._2 instanceof $$)
					return;
				int i = 1;
				while (!(current._2 instanceof $$))
				{
					if (i >= refs.length)
						return;
					current = ($)current._2;
					refs[i]._1 = current._1;
					i++;
				}
			}
 
		};
 
	}
}
 
class £<T> extends $<T,$$>
{
	protected £(T t)
	{
		super(t,$$);
	}
 
	public static <T> £<T> £(T t)
	{
		return new £<T>(t);
	}
 
	public static <T> T £(£<T> t)
	{
		return t._1;
	}
}

Posted by & filed under Java, Uncategorized.

We often discuss Java limitations on IRC and try to come up with (sometimes silly) workarounds. Unfortunately after time passes it’s often easy to forget the outcome, and lose code snippets. So I thought I’d start blogging some of them so I don’t lose them, and other people might suggest other ways of doing things that we’ve overlooked.

This particular problem occurs when you want to assign the result of a method that can throw an exception to a final variable. For example:

final Customer c;
try
{
	c = getCustomer(id);
} catch (CustomerNotFoundException e)
{
	c = createNewCustomer();
}

This will fail to compile with “variable c might already have been assigned”. Of course making c not final would solve the problem, but that’s no fun.

If we were not using Exceptions, Java provides a useful ternary operator “?:” that lets us do things like:

final Customer c = customerExists(id) ? getCustomer(id) : createNewCustomer();

Which is nice and clean, but means that getCustomer is going to have to return null or throw a RuntimeException in the case that there is no matching customer, which is undesirable. Also customerExists() may be expensive.

We could also possibly use something along the lines of

final Option<Customer> c = getCustomer();

Both of these alternatives, however, require changing the API you’re consuming, and avoiding Exceptions. It would be nice if there was an equivalent of “?:” for try/catch so that you could assign the result to a final variable. The best I can manage in Java is below, can anyone do better?

import java.lang.reflect.ParameterizedType;
 
abstract class TryCatch<T, U extends Exception>
{
	public T value()
	{
		try
		{
			return Try();
		} catch (Exception e)
		{
			if (getTypeOfU().isAssignableFrom(e.getClass()))
			{
				return Catch();
			} else
			{
				throw new RuntimeException(e);
			}
		}
	}
 
	@SuppressWarnings("unchecked")
	private Class<U> getTypeOfU()
	{
		return (Class<U>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[1];
	}
 
	public abstract T Try() throws U;
 
	public abstract T Catch();
}
 
//Example
public class Main
{
	private static CustomerRepo repo = new CustomerRepo();
 
	public static void main(String[] args) 
	{
		final Customer c = new TryCatch<Customer, CustomerNotFoundException>()
		{
			public Customer Try() throws CustomerNotFoundException
			{
				System.out.println("in try");
				return repo.getCustomer(1);
			}
 
			public Customer Catch()
			{
				System.out.println("in catch");
				return repo.createCustomer();
			}
		}.value();
	}
 
}
 
class CustomerRepo
{
 
	public Customer getCustomer(int id) throws CustomerNotFoundException
	{
		throw new CustomerNotFoundException();
	}
 
	public Customer createCustomer()
	{
		return new Customer();
	}
}
 
class Customer
{
}
 
class CustomerNotFoundException extends Exception
{
}

In C# we don’t run into the same problem since readonly is much less useful than Java’s final. However, if we wanted to try/catch at the same time we can do a bit better. Here’s an alternative in C#:

using System;
 
public class Example
{
	public static void Main()
	{
		Example t = new Example();
		t.Foo();
	}
 
	public void Foo()
	{
		String result1 = this.Try(() => GetBar(true)).Catch<BarException>(() => "Caught a BarException");
		String result2 = this.Try(() => GetBar(false)).Catch<BarException>(() => "Caught a BarException");
		Console.WriteLine(result1);
		Console.WriteLine(result2);
	}
 
	public String GetBar(bool succeed)
	{
		if (succeed)
			return "Success!";
		else
			throw new BarException();
	}
}
 
public class BarException : Exception {}
 
public class Tryer<TResult>
{
	private readonly Func<TResult> toTry;
	internal Tryer(Func<TResult> toTry)
	{
		this.toTry = toTry;
	}
 
	public TResult Catch<TException>(Func<TResult> whenCaught)
		where TException : Exception
	{
		try
		{
			return toTry();
		} catch (TException)
		{
			return whenCaught();
		}
	}
}
 
namespace System
{
	public static class ProvidesTry
	{
		public static Tryer<TResult> Try<T,TResult>(this T other, Func<TResult> toTry)
		{
			return new Tryer<TResult>(toTry);
		} 
	}
}

Posted by & filed under Uncategorized.

In the last couple of weeks I’ve had some time to work on the software portal project for the first time for a while.

There is now a test snapshot that you can play with if you wish, and help find bugs.

Please do have a play and leave comments here or file a bug report under the Software Portal component.

You’ll need to register to add comments/screenshots/tags etc. Unfortunately since the account you use to login to other openSUSE.org services is controlled by Novell and they provide no openid/saml facility you cannot use the same user account. If you want permissions to edit application details just send me an email (benji at opensuse dot org).

Most of the recent work has been under the hood. Significant speed improvements to the repository indexer and a Webpin compatible webservice that will enable the various clients to continue to work against software portal as they did with webpin until they can be ported to the new api.

There are also some visible changes. The homepage now displays recent comments & top rated applications, and includes the tag cloud.

Software Portal Home Page

Users can now choose a specific vendor for an application for their distribution, as well as installing from the preferred vendor.

Editors can now customise which source packages map to which application.

and which binary packages should be installed by default when a user clicks install.