Showing posts with label jdk8. Show all posts
Showing posts with label jdk8. Show all posts

Monday, August 15, 2016

What is bound to generic types for method references in java 8, types and exceptions

So most of the time you are probably aware of method references that either reference instance of static methods directly, and they are useful but not necessarily that interesting.

Integer example = 1;

// We can bind the instance variables, in this case just the return type is bound but there couple be method parameters also
Supplier<String> s = example::toString;

// We can bind to static method, here the generic parameter are the method parameter and return type
Supplier<Long> f = System::currentTimeMillis;
Function<Integer,Integer> f = example::compareTo;


A less common formulation is to pass in instance methods and find the first generic parameter of of the function to be the type, this allows you to easily pass in a range of actions to operate on a common type:

Function<Integer,String> f = Integer::toString

For example you can create an equals method that works on a subset of properties using functions mapped to instance methods as in the above example:

public static <T> boolean equals(T one, T two, Function<? super T, ?>... accessors) {

    if (one == two) {
        return true;
    } else  if (one==null || two==null) {
        return false;
    }

    return Stream.of(accessors).allMatch(accessor ->
        Objects.equals(accessor.apply(one),accessor.apply(two)));
}

if (equals(one, two, Thing::getName, Thing:getOtherProperty)) ...;



Finally you can also bind the exception thrown from the method to one of the generic parameters. (Here I am using ThrowingException and ThrowingSupplier my home brew interfaces that are like there namesakes but have a generic parameter E for the exception thrown) This allows you to make you "closure" transparent to exceptions. This is more useful in a lot of cases when compared to the Stream throw nothing and "throws Exception" extremes.

ThrowingException<String,Integer,NumberFormatException> te = Integer::parseInt;


You can write funky closure methods that will throw different exceptions based on the passed in method reference does, no more catch (Exception).

public static <T, E extends Exception> T withCC(Class<?> contextClass, 
   ThrowingSupplier<T,E> action) throws E {

    Thread t = Thread.current();
    ClassLoader cl = t.getContextClassLoader();
    try {
        t.setContextClassLoader(contextClass.getClassLoader());
        return action.get();
    } finally {
        s.setContextClassLoader(cl);
    }
}
       

// Throws IOException, complier knows that this method call throws IOException

String value = withCC(Example.class, () -> {
    ...
    ... new FileOutpuStream(file); ...
    ...
});

// Throws another exception, complier knows that this method call throws RMIExeption

String value = withCC(Example.class, () -> {
        ...
        throw new RMIException();
    });


Once you understand the last two, method reference start to become far more interesting.

Thursday, June 2, 2016

Getting a name for someone to connect back to your server.

When doing test automation it is often the case you need to know the name of the current machine in order to prompt another machine to connect to it, particularly if you are running your tests in parallel. This week I was trying to get the server under test to connect back to a WireMock server running on the slave test machine.

The standard response on stack overflow is to use the following pattern to get a network address. In my version here if we can't resolve the name then we are assuming we are running on a developers laptop on VPN so all the tests are run on the same machine. (Hence localhost)

String hostName = "localhost";
try {
    InetAddress addr = InetAddress.getLocalHost();
    String suggestedName = addr.getCanonicalHostName();
    // Rough test for IP address, if IP address assume a local lookup
    // on VPN
    if (!suggestedName.matches("(\\d{1,3}\\.?){4}") && !suggestedName.contains(":")) {
        hostName = suggestedName;
    }
} catch (UnknownHostException ex) {
}

System.out.println(hostName);

The problem comes is that we have to trust the local machine settings, for example /etc/hostname, which can result in a network name that is not accessible from another machine. To counter this I wrote the following code to work over the available network interfaces to find a remotely addressable network address name that can be used to talk back to this machine. (I could use an IP address but they are harder to remember, particularly as we are moving towards IPv6)

String hostName = stream(wrap(NetworkInterface::getNetworkInterfaces).get())
        // Only alllow interfaces that are functioning
        .filter(wrap(NetworkInterface::isUp))
        // Flat map to any bound addresses
        .flatMap(n -> stream(n.getInetAddresses()))
        // Fiter out any local addresses
        .filter(ia -> !ia.isAnyLocalAddress() && !ia.isLinkLocalAddress() && !ia.isLoopbackAddress())
        // Map to a name
        .map(InetAddress::getCanonicalHostName)
        // Ignore if we just got an IP back
        .filter(suggestedName -> !suggestedName.matches("(\\d{1,3}\\.?){4}")
                                 && !suggestedName.contains(":"))
        .findFirst()
        // In my case default to localhost
        .orElse("localhost");

System.out.println(hostName);

You might notice there a are a few support methods being used in there to tidy up the code, here are the required support methods if you are interested.

@FunctionalInterface
public interface ThrowingPredicate<T, E extends Exception>{

    boolean test(T t) throws E;
}

@FunctionalInterface
public interface ThrowingSupplier<T, E extends Exception>{

    T get() throws E;
}

public static <T, E extends Exception> Predicate<T> wrap(ThrowingPredicate<T, E> th) {
    return t -> {
        try {
            return th.test(t);
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    };
}

public static <T, E extends Exception> Supplier<T> wrap(ThrowingSupplier<T, E> th) {
    return () -> {
        try {
            return th.get();
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    };
}

// http://stackoverflow.com/a/23276455
public static <T> Stream<T> stream(Enumeration<T> e) {
    return StreamSupport.stream(
            Spliterators.spliteratorUnknownSize(
                    new Iterator<T>() {
                public T next() {
                    return e.nextElement();
                }

                public boolean hasNext() {
                    return e.hasMoreElements();
                }
            },
                    Spliterator.ORDERED), false);
}

Thursday, April 7, 2016

Converting string configuration properties to other types, with a bit of Optional.

Somedays you come across some code and think that's pretty, why didn't I think of that? So my long time colleague Mark Warner has a nice twist on the standard name/value store pattern using method references to deal with converting from a String.

int size = store.getProperty("cache.limit", 500, Integer::parseInt);
    boolean enabled = store.getProperty("cache.enabled", true, Boolean::getBoolean);

I took his example and refactored it slightly to return Optional, and I ended up with the following:

public Optional<String> getProperty(
        String propertyName) {
    return Optional.ofNullable(map.get(propertyName));
}
   
public <T> Optional<T> getProperty(
        String propertyName, 
        ThrowingFunction<String,? extends T,? extends Exception> func ) {

    return getProperty(propertyName).map(val -> {
        try {
            return func.apply( val );
        } catch ( Exception e ) {
            LOGGER.severe( () -> "Invalid property transform, will default " + e.getMessage() );
            return null;
        }
    });
}

This means that the default value ends up being provided by the Optional which is a nice application of OAOO.

int size = store.getProperty("cache.limit", Integer::parseInt).orElse(500);
    boolean enabled = store.getProperty("cache.enabled", Boolean::getBoolean).orElse(true);

I think this is even tidier; but it does depend on who you feel about using Optionals.

Thursday, March 10, 2016

Lambda of Lambda, if/else from an Optional

So I got frustrated with two limitations of the Optional interface in JDK 8. The first problem is that there is no obvious way to perform an else operation in a block as there is only a isPresent method unless you are using an old school if statement. The second problem is of course the old chestnut that even if you could do that the methods would not be able to throw a checked exception. (Yes you can wrap with a RuntimeException but it is not the prettiest.)

The workaround I found was to use the map function as the success case and the orElseGet to return the failure case. In both branches the code returns an instance of ThrowingRunnable by having a lambda return a lambda. The run() is then called at the end and it can throw any exception it wants to.

@FunctionalInterface
public interface ThrowingRunnable<E extends Throwable>  {
    
    public void run() throws E;
}



Optional<Credential> credential = ....

credential.<ThrowingRunnable<IOException>>map(auth -> () -> {
                PasswordWrapper pw = auth.getToken();
                ... // something that might throw an IOException
            }).orElseGet(() -> () -> {
                        response.setStatus(401);
                        LOGGER.log(Level.INFO, "credential is not found");
                    }
            ).run();


This is possibly excessive for this particular use case; but I can see this technique being useful elsewhere and it is worth knowing what it looks like so it is not a surprise in others code.

Update 14th March 2016: Thanks to Michael Rasmussen on the DZone version of this article he noted I could use orElse rather than orElseGet to remove the second double lambda.

credential.<ThrowingRunnable<IOException>>map(auth -> () -> {
                PasswordWrapper pw = auth.getToken();
                ... // something that might throw an IOException
            }).orElse(() -> {
                        response.setStatus(401);
                        LOGGER.log(Level.INFO, "credential is not found");
                    }
            ).run();



Tuesday, January 12, 2016

Beware of slightly different behaviour between ConcurrentMap and ConcurrentHashMap for computeIfAbsent

So I was refactoring some code to use non-locking collection classes and I noticed the this significant different between ConcurrentMap.computeIfAbsent and ConcurrentHashMap.computeIfAbsent. They key different is that for the former default implementing the mapping function can be called many times for a particular key where as for the concrete implementation it will be called only once. This will likely affect whether the code in the function needs to be thread safe or not.

Right okay so armed with that you know that any collection that implements just ConcurrentMap will inherit this behaviour, further to that I found in particular guava would return a different implementation depending on the passed on parameters:

ConcurrentMap map1 = new MapMaker().makeMap();
System.out.println(map1.getClass());

ConcurrentMap map2 = new MapMaker().weakKeys().makeMap();
System.out.println(map2.getClass());

....

class java.util.concurrent.ConcurrentHashMap
class com.google.common.collect.MapMakerInternalMap

MapMakerInternalMap doesn't override computerIfAbsent therefore the behaviour of this function will be significantly different depending on the parameters to pass into the maker, something that might be apparent from the get go.

Thursday, December 19, 2013

Lambda'ery WebSocket code (from UKTECH13 presentation)

At UKTECH13 I was asked to post the source code to the WebSocket used in my presentation, primarily because it was using JDK 8 constructs that were unfamiliar to many. One of the very nice things about the changes to the languages and the supporting library changes is the lack of if statements in the code.

I would note that in a real world chat application that it unlikely different rooms would have different resource URIs but for the purposes of the presentation this made sense.

package websocket;

import static java.util.Collections.emptySet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArraySet;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint(value = "/chat/{room}")
public class ChatService {

  private static final Set<Session> EMPTY_ROOM = emptySet();

  static final ConcurrentMap<String, Set<Session>> rooms =
    new ConcurrentHashMap<>(); 


  @OnOpen
  public void onOpen(Session peer, @PathParam("room") String room) {
    rooms.computeIfAbsent(room,
                          s -> new CopyOnWriteArraySet<Session>()).add(peer);
  }

  @OnClose
  public void onClose(Session peer, @PathParam("room") String room) {

    rooms.getOrDefault(room, EMPTY_ROOM).remove(peer);
    
  }

  @OnError
  public void onError(Session peer, Throwable th,
                      @PathParam("room") String room) {
    System.out.println("Peer error " + room + " " + th);
  }


  @OnMessage
  public void message(String message, Session peer,
                      @PathParam("room") String room) {

    // Send a message to all peers in a room who are not the current
    // peer and are still open. Send the message asynchronously to ensure
    // that the first client is not hung up. 

    rooms.getOrDefault(room, EMPTY_ROOM).parallelStream()
         .filter(s -> s != peer && s.isOpen())
         .forEach(s -> s.getAsyncRemote().sendObject(message));
  };

}

One of the problem with the above design is that there is no error logging when an invalid room is used. This could be useful to diagnose errors. Not wanting to use any conditional statements you could use an Optional object:

import java.util.Optional;


  @OnClose
  public void onClose(Session peer, @PathParam("room") String room) {

    Optional.ofNullable(rooms.get(room))
      .orElseThrow(() -> new IllegalStateException("Cannot find room " + room))
      .remove(peer);
    
  }


Of course you might want this on your method objects, so you can use default methods to create a mixin for this on all your Map objects with a trivial subclass.

import java.util.Optional;


  public interface OptionalMap<K,V> extends ConcurrentMap<K,V> {
     public default Optional<V> find(K key) {
        return Optional.ofNullable(get(key));
     }
  }

  public static class OptionalHashMap<K,V> extends ConcurrentHashMap<K,V>
   implements OptionalMap<K,V> {
       
  }
    

  static final OptionalMap<String, Set<Session>> rooms =
    new OptionalHashMap<>(); 


  @OnClose
  public void onClose(Session peer, @PathParam("room") String room) {

    rooms.find(room)
      .orElseThrow(() -> new IllegalStateException("Cannot find room " + room))
      .remove(peer);
    
  }





Whilst working on my presentation it became apparent that it was also possible to use the "openSessions" and "getUserProperties" method to store discrimination data against the Session. I don't have enough experience yet to say which is the better design for a particular case.

package websocket;


import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint(value = "/chat/{room}")
public class ChatService {

  private static final String ROOM_PROPERTY = "ROOM";


  @OnOpen
  public void onOpen(Session peer, @PathParam("room") String room) {
    peer.getUserProperties().put(ROOM_PROPERTY, room);
  }

  @OnClose
  public void onClose(Session peer, @PathParam("room") String room) {
    
    // No need to tidy up and data is store against peer
  }

  @OnError
  public void onError(Session peer, Throwable th,
                      @PathParam("room") String room) {
    System.out.println("Peer error " + room + " " + th);
  }


  @OnMessage
  public void message(String message, Session peer,
                      @PathParam("room") String room) {

    peer.getOpenSessions().parallelStream()
         .filter(s -> room.equals(s.getUserProperties().get(ROOM_PROPERTY)))
         .filter(s -> s != peer && s.isOpen())
         .forEach(s -> s.getAsyncRemote().sendObject(message));
  };

}

Wednesday, December 4, 2013

Lambda, will it serialize?

So I have been ponder an enhancement required on the Tyrus project that would allow a user to broadcast to a subset of client connected to a URL across a cluster of machines. There are various way of doing this; but since I was playing with JDK 8 this problem definitely looked like a nail.

To this end I created a simple unit test class that would take my filter, serialise it to disk, read it back and in then execute it. It had a instance field "VALUE" that we could use to reference directly or indirectly to find out what would cause the serialisation to fail.

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.NotSerializableException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.Serializable;

import java.util.function.Predicate;

import org.junit.Test;

public class SerializablePredicateFilterTest {

  public String VALUE = "Bob";

  public interface SerializablePredicate<T> extends Predicate<T>, Serializable {

  }


  public <T> void filter(SerializablePredicate<T> sp, T value) throws IOException, ClassNotFoundException {


    sp.getClass().isLocalClass();

    File tempFile = File.createTempFile("labmda", "set");


    try (ObjectOutput oo = new ObjectOutputStream(new FileOutputStream(tempFile))) {
      oo.writeObject(sp);
    }


    try (ObjectInput oi = new ObjectInputStream(new FileInputStream(tempFile))) {
      SerializablePredicate<T> p = (SerializablePredicate<T>) oi.readObject();

      System.out.println(p.test(value));
    }


  }

}


So just to calibrate lets make sure that an anonymous inner class will fail, because it will always contain a reference to enclosing object....

  @Test(expected = NotSerializableException.class)
  public void testAnonymousDirect() throws IOException, ClassNotFoundException {

    String value = VALUE;


    filter(new SerializablePredicate<String>() {

      @Override
      public boolean test(String t) {
        return value.length() > t.length();
      }
    }, "Bob");

  }


The same is true for local classes, what you don't use local classes?

  @Test(expected = NotSerializableException.class)
  public void testLocalClass() throws IOException, ClassNotFoundException {

    class LocalPredicate implements SerializablePredicate<String> {
      @Override
      public boolean test(String t) {
        // TODO Implement this method
        return false;
      }
    }

    filter(new LocalPredicate(), "Bobby");

  }


So a standalone class will of course work, in this case a nested class for convenience.

  public static class LengthPredicate implements SerializablePredicate<String> {

    private String value;


    public LengthPredicate(String value) {
      super();
      this.value = value;
    }

    public void setValue(String value) {
      this.value = value;
    }

    public String getValue() {
      return value;
    }

    @Override
    public boolean test(String t) {
      // TODO Implement this method
      return false;
    }
  }


  @Test
  public void testStaticInnerClass() throws IOException, ClassNotFoundException {

    filter(new LengthPredicate(VALUE), "Bobby");

  }


So lets get down with JDK 8, it turns out that my first try also fails but it does confirm that the serialisation is quite happy to take a Lambda in general.

  @Test(expected = NotSerializableException.class)
  public void testLambdaDirect() throws IOException, ClassNotFoundException {


    filter((String s) -> VALUE.length() > s.length(), "Bobby");

  }


A slight modification to copy the value into a effectively final attributes, and voila the lambda is now serialised and retrieved properly.

  @Test
  public void testLambdaInDirect() throws IOException, ClassNotFoundException {

    String value = VALUE;

    filter((String s) -> value.length() > s.length(), "Bobby");

  }


And of course if the value is a simple method parameter it also works fine.


  @Test
  public void testLambdaParameter() throws IOException, ClassNotFoundException {

    invokeWithParameter(VALUE);

  }

  private void invokeWithParameter(String value) throws java.lang.ClassNotFoundException, java.io.IOException {
    filter((String s) -> value.length() > s.length(), "Bobby");
  }


So the answer is yes, you can get it to serialise if you are a bit careful.

Friday, August 9, 2013

Almost named method arguments in JDK 8

Sometimes it would be really nice to have named method parameter in Java, this doesn't look likely for a long while but there is always another little work around, for example using a builder pattern to get similar behaviour, that will bridge the gap for a little bit. It occurred to me that using the Lambda support in JDK 8 you could get something very close without the boiler plate required by some of the other methods.

So consider this simple Facade class, that presents a method with a variable list of parameters. Note the variant of the method that takes in a Consumer object - this is what we are going to invoke with a Lambda later on.

package client;

import java.util.function.Consumer;

public class Facade {
    
    public static void invoke(Consumer<Parameter> op) {
        
        Parameter p = new Parameter();
        op.accept(new Parameter());
        invoke(p);        
    }
    
    public static void invoke(Parameter p) {

        // Defensive copy and validate
        p = p.clone();
        p.validate();
        
        // ...
    }

    
    public static class Parameter implements Cloneable {
        public String value1, value2, value3;
        
        public Parameter validate() {
            // ...
            
            return this;
        }

        public Parameter clone() {
            // We can use vanilla clone here, for more complicated mutable objects
            // you might need to perform a deeper copy
            try {
                return (Parameter) super.clone();
            } catch (CloneNotSupportedException e) {
                throw new RuntimeException(e);
            }
        }
    }
    
}

So once you have this in place, you can use Lambda notation to call the invoke method with how every many parameters as you might think suitable:

...
{

    public static void main(String[] args) {
        
        // Single parameter version
        Facade.invoke(p ->  p.value1="x" );
        // Multiple parameter version
        Facade.invoke(p -> { p.value1="x"; p.value2="y";});
    }
}

Of course the eagle eyed of your will recognise that the same pattern, minus the Consumer method of course, with an earlier JDK. Given the number of java developers out there some-one probably will have probably already invented this pattern; but you never know and if you don't write it down the thought it didn't happen.

...
{

    public static void main(String[] args) {
        
        // Using an anonymous inner class pre JDK 8
        Facade.invoke(new Parameter() {{
            value1 = "x";
            value2 = "y";
        }});
    }
}