Category Archives for Java

What does Spring DelegatingFilterProxy do?

What does Spring DelegatingFilterProxy do? I had never given it much thought about how Spring Security integrates with web.xml until I had to diagnose an issue involving the DelegatingFilterProxy and my Spring Security configuration.

Isle Of Harris

What does Spring DelegatingFilterProxy do?

I knew the starting point is the springSecurityFilterChain which uses the DelegatingFilterProxy, and this would instantiate the Spring Security filters according to my spring configuration –

    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
    </filter-mapping

But what next?

DelegatingFilterProxy

A look at the javadoc for DelegatingFilterProxy states that –

Proxy for a standard Servlet Filter, delegating to a Spring-managed bean that implements the Filter interface

It further states that the filter-name corresponds to a bean in the Spring application context.

So in terms of Spring Security the DelegatingFilterProxy will look though the Spring Application Context for a bean “springSecurityFilterChain”. The only requirement for Delegated beans is that they must implement javax.servlet.Filter.

Initializing the springSecurityFilterChain

The springSecurityFilterChain is initialised in your spring configuration by, which will be passed to your DispatcherServlet –

<http ...> </http>

We can see this in action when we include code to add remove filters in Spring Security –

<http ...>
    ...        
    <custom-filter ref="mySecurityFilter" after="FORM_LOGIN_FILTER"  />
    ...
</http>

You can also see a list of filters created when you up spring security logging

What about Spring Boot?

Spring Security configuration for Spring Boot is simply a matter of adding a reference to “spring-boot-starter-security” to gradle or maven. We can then fine tune the security configurations through @EnableWebSecurity and overriding the configure method of a class extending WebSecurityConfigurerAdapter.

If we dig around under the hood we find that the DelegatingFilterProxy is still used. With the “springSecurityFilterChain” instantiated in SecurityFilterAutoConfiguration, which populates the DelegatingFilterProxyRegistrationBean with “springSecurityFilterChain” (AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME) –

@Bean
@ConditionalOnBean(name = DEFAULT_FILTER_NAME)
public DelegatingFilterProxyRegistrationBean securityFilterChainRegistration(SecurityProperties securityProperties) {
    DelegatingFilterProxyRegistrationBean registration = new DelegatingFilterProxyRegistrationBean(DEFAULT_FILTER_NAME);
    registration.setOrder(securityProperties.getFilterOrder());
    registration.setDispatcherTypes(getDispatcherTypes(securityProperties));
    return registration;
}

Reference

http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#delegating-filter-proxy

https://spring.io/blog/2013/07/03/spring-security-java-config-preview-web-security/

http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#delegating-filter-proxy

Keeping Documentation Up-To-Date

I returned to a project wiki on confluence after a few months break, and was looking through the documentation wondering if it was still relevent. The code and requirements had changed in places, so I knew some was out of date – however the documentation of the new areas looked good. There were also other design artifacts that seemed important at the time, but now I felt had questionable value.

Problem

In my experience the problem is that we create lots documentation at the start of a project to set direction, but as the project continues it becomes easier to see how the requirements slot into the overall design. This means we are less likely to update the documentation in these areas as they are covered at a high level in the existing documentation. This means the information can slip through the cracks.

Solutions?

I’ve had a look into solutions to this problem –

  • Aims – What do you need to document? From a developer perspective you likely need –
    • Onboarding
    • UML artifacts – Class Diagrams, Sequence Diagrams
    • Server setups might also be relevent
  • Pruning – At the end of a project, or phase, have a task to prune the information. The degree to which you “prune” the information depends on your project. If you are using a wiki you could reference the access log to see when the pages were last used, and there are some tools that can auto-archive but I have not used these.
  • Autogenerate content – This is especially important for documenting software – but look to use tools to generate your design documentation
  • Fresh Eyes – We only see the true value of documentation when we onboard someone new, or return to a project after a break. Then we get to see the cracks in the documentation, and what is not of value

Other?

I would be interested to read how other people manage project documentation, especially in small teams

Java8 – Methods in Interfaces

My previous post on streams demonstrates how useful this feature is to Java8. However it created a problem for the API designers. The problem was how to we extend the existing Collection’s API without breaking existing Collections implementations(guava, apache).

The solution was to allow methods in interfaces, meaning that any implementations already carry an implementation of the extension.

A good example is –

public interface Collection extends Iterable {
    // ....
    default Stream stream() {
        return StreamSupport.stream(spliterator(), false);
    }
    // ....
}

Rules on default methods

  • Always public
  • default – keyword

Multiple Inheritance

Java always had multiple inheritance in interfaces, but it wasn’t an issue as it didn’t matter which version of the inherited method was implemented.

interface Fred {
    void run();
}
public class OldSkoolMultipleInheritance implements Runnable, Fred {
    @Override
    public void run() {
        System.out.println("Runnable and Fred share the method signature run()");
    }
}

It’s more complex when default methods are involved, and java 8 has an order of precedence –

  • classes > interfaces
  • children > parent
  • else select or override implementation

Examples

interface Interface1 {
    default void defaultMethod() {
        System.out.println("print me!");
    }
}
interface Interface2 {
    default void defaultMethod() {
        System.out.println("no print me!");
    }
}
  • Classes > Interfaces –
public class DefaultMethodMultipleInheritance implements Interface1, Interface2 {
    @Override
    public void defaultMethod() {
        System.out.println("I win");
    }
}
  • Child Interfaces > Parent Interfaces –
interface Interface3 extends Interface2 {
    default void defaultMethod() {
        System.out.println("No no print me!!!");
    }
}
public class DefaultMethodMultipleInheritance implements Interface2, Interface3 {
    public static void main(String[] args) {
        new DefaultMethodMultipleInheritance().defaultMethod();
    }
}
Output - No no print me!!!
  • Re-implement method in the DefaultMethodsClass and call the specific implementation using super –
Interface1.super.newWave(); or Interface2.super.newWave();

eg –

public class DefaultMethodMultipleInheritance implements Interface1, Interface2 {
    @Override
    public void defaultMethod() {
        Interface1.super.defaultMethod();
    }
}

static methods

The reasoning here is to keep static methods specific to your interface in one location –

  • public
  • static
  • Never inherited

Java8 – Date and Time examples

This post continues my look at Java8 features with the date API, including examples.

Before Java8 we had two date implementations – java.util.Date and java.util.Calendar. These implementations had numerous issues which Java8 sought to resolve. This article considers these issues, as well as providing a examples using the java.time API.

Issues

  • API Design – java.util.Date and java.util.Calendar both had issues like months starting from 0, or in the case of Date year starting from 1900. Date also represented a point in time, seconds from the epoch, while its toString method included a TimeZone. There was also no single class representing Time or Date
  • Thread-safety – DateFormat not thread safe

De-facto standards – Joda-Time evolved as a defacto standard for Java dates. It is to Java8’s credit that they developed the Java8 JSR-310 API’s with the main joda-time developer Stephen Colebourne.

New Features

  • New package – java.time.*
  • Core Classes – LocalDate, LocalTime, LocalDateTime, ZonedDateTime, Period, Duration, Instant
  • Immutable
  • Factory methods

Examples

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Period;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAdjusters;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

public class DateTimeExamples {

	public static void main(String[] args) {
		preJava8DateAndCalendar();
		java8LocalDateAndLocalTimeExamples();
		java8LocalDateTimeExamples();
		java8ZonedDateTime();
		java8CustomAdjuster();
		java8PeriodOrDuration();
	}

	public static void preJava8DateAndCalendar() {
		System.out.println("\npreJava8DateAndCalendar\n");

		Date today = new Date();
		System.out.println("Note the time includes the default timezone - " + today.toString());

		Date twentySevenFeb2017Date = new Date(117, 1, 27);
		System.out.println("Now deprecated new Date(day, month, year) - but note month starts at zero, and year 1900 - " + twentySevenFeb2017Date);

		Calendar twentySevenFeb2017Calendar = new GregorianCalendar(2017,1,27);
		System.out.println("Calendar - month starts at zero, and but year fixed - " + twentySevenFeb2017Calendar.getTime());

		DateFormat ddMMyyySDF = new SimpleDateFormat("dd/MM/yyyy");
		System.out.println("DateFormat not ThreadSafe - " + ddMMyyySDF.format(twentySevenFeb2017Date));
	}

	public static void java8LocalDateAndLocalTimeExamples() {
		// Date and Time split up - LocalDate, LocalTime
		// Called through factory methods of, now, parse
		// Immutable
		// No TimeZone
		System.out.println("\njava8LocalDateAndLocalTimeExamples\n");

		LocalDate currentLocalDate = LocalDate.now();
		System.out.println("currentLocalDate - yyyy-MM-dd - " + currentLocalDate);

		// Month now not based on 0, and year not based on 1900
		LocalDate twentySevenFeb2017LocalDate = LocalDate.of(2017, 2, 27);
		System.out.println("twentySevenFeb2017LocalDate - yyyy-MM-dd - " + twentySevenFeb2017LocalDate);

		twentySevenFeb2017LocalDate = twentySevenFeb2017LocalDate.withYear(2017).withMonth(12).withDayOfMonth(25);
		System.out.println("twentySevenFeb2017LocalDate - with -  " + twentySevenFeb2017LocalDate);

		LocalDate parseTwentySevenFeb2017LocalDate = LocalDate.parse("2017-02-27", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
		System.out.println("parseTwentySevenFeb2017LocalDate - pattern - yyyy-MM-dd - " + parseTwentySevenFeb2017LocalDate);

		// increment using plus, decrement using minus
		twentySevenFeb2017LocalDate = twentySevenFeb2017LocalDate.plusDays(1);
		System.out.println("twentySevenFeb2017LocalDate - immutable - " + twentySevenFeb2017LocalDate);

		// Time with no date
		LocalTime currentLocalTime = LocalTime.now();
		System.out.println("currentLocalTime - yyyy-MM-dd - " + currentLocalTime);

		LocalTime parseLocalTime = LocalTime.parse("13:44");
		System.out.println("parseLocalTime - " + parseLocalTime);

		parseLocalTime = LocalTime.parse("13:44:25");
		System.out.println("parseLocalTime - immutable - " + parseLocalTime);

	}

	public static void java8LocalDateTimeExamples() {
		// Combines LocalDate and LocalTime
		// Called through factory methods of, now, parse
		// Immutable
		// No TimeZone
		System.out.println("\njava8LocalDateTimeExamples\n");

		LocalDateTime currentLocalDateTime = LocalDateTime.now();
		System.out.println("currentLocalDateTime " + currentLocalDateTime);		

		currentLocalDateTime = LocalDateTime.parse("2019-06-21T23:53:00.123");
		System.out.println("currentLocalDateTime - parse -  " + currentLocalDateTime);

		currentLocalDateTime = currentLocalDateTime.minusYears(10);
		System.out.println("currentLocalDateTime - minus 10 years -  " + currentLocalDateTime);
	}

	public static void java8ZonedDateTime() {
		System.out.println("\njava8ZonedDateTime\n");

		// Associate DateTime with TimeZone
		ZonedDateTime zonedDateTime = ZonedDateTime.of(LocalDateTime.now(), ZoneId.systemDefault());
		System.out.println("zonedDateTime - " + zonedDateTime);

		ZoneId australiaSydneyZoneId = ZoneId.of("Australia/Sydney");
		ZonedDateTime australiaSydneyZonedDateTime = ZonedDateTime.of(LocalDateTime.now(), australiaSydneyZoneId);
		System.out.println("australiaSydneyZonedDateTime - " + australiaSydneyZonedDateTime);
	}	

	public static void java8CustomAdjuster() {
		System.out.println("\njava8CustomAdjuster\n");
		TemporalAdjuster dueDateAdjuster = TemporalAdjusters.ofDateAdjuster((LocalDate localDate) -&amp;gt; localDate.plusWeeks(40));

		LocalDate startLocalDate = LocalDate.now();
		System.out.println("Due Date - " + startLocalDate.with(dueDateAdjuster));
	}

	public static void java8PeriodOrDuration() {
		System.out.println("\njava8DurationPeriodAndInstance\n");
		// Period - Duration in day, weeks, month, years
		Period examplePeriod = Period.of(72,6,10);
		System.out.println("examplePeriod " + examplePeriod);

		LocalDate localDatePlusExamplePeriod = LocalDate.now().plus(examplePeriod);
		System.out.println("localDatePlusExamplePeriod " + localDatePlusExamplePeriod);

		// Duration - days, hours, minutes, seconds
		Duration exampleDuration = Duration.ofHours(5);
		System.out.println("exampleDuration " + exampleDuration);

		LocalTime exampleDurationLocalTime = LocalTime.now().plus(exampleDuration);
		System.out.println("exampleDurationLocalTime " + exampleDurationLocalTime);		

	}	

}

Java8 – Optional’s Overview with Examples

We can limit the opportunities for NullPointerException’s by following good practice like –

  • Don’t return null’s from methods
  • Don’t pass null’s as arguments

Another tool is to use java.lang.Optional. Java8 optional formalises the approach used in other languages, and already existed in some Java libraries. Optional is simply an object wrapper. The key to its use is to use the methods in the Optional classes.

Examples

Im following a similar style to my last post Java8 – Streams Cookbook and have included a class with a number of examples using Optional

import java.util.Optional;
public class OptionalExamples {
	// Populate Bike with Optional<Wheels>
	private static Bike colnagoBike = new Bike(Optional.of(new Wheels("mavic", 32)), "colnago");
	// Dont do this - use a Optional.ofNullable
	private static Bike nullBike = new Bike(null, "nowheels");
	// Use a Optional.ofNullable
	private static Bike ofNullableBike = new Bike(Optional.ofNullable(null), "nowheels");
	public static void main(String[] args) {
		emptyOptionals();
		nullObjectsInOptionals();
		workingWithValuesInOptionals();
	}
	private static void workingWithValuesInOptionals() {
		// Working with Values
		// Populated Optional - now begin populating with Object
		Optional<Bike> optionalColnagoBike = Optional.of(colnagoBike);
		if (optionalColnagoBike.isPresent()) {
			System.out.println("isPresent() - ok - but not much improvement on != null");
		}
		optionalColnagoBike.ifPresent(bike -> System.out.println("ifPresent(Consumer) returns " + bike.getBrand()));
		// Filtering and mapping in combination with Lambdas
		Bike orElseThrowBike = optionalColnagoBike.filter(b -> "colnago".equals(b.getBrand())).get();
		//
		Optional<String> brand = optionalColnagoBike.map(b -> b.getBrand());
		brand.ifPresent(b -> System.out.println("brand " + b));
		// flatMap to prevent Optional<Optional<Wheels>>
		Optional<Wheels> wheels = optionalColnagoBike.flatMap(b -> b.getWheels());
		wheels.ifPresent(w -> System.out.println("flatMap - Wheel Brand " + w.getBrand()));
	}
	private static void nullObjectsInOptionals() {
		// of - Populate with null object - Throws Exception
		try {
			Optional<Bike> optionalNullBike = Optional.of(null);
		} catch (java.lang.NullPointerException nfe) {
			System.out.println("Cant call Optional.of(null) - " + nfe.getMessage());
		}
		// ofNullable - allows null
		System.out.println("We can pass a null with ofNullable");
		Optional<Bike> optionalOfNullableBike = Optional.ofNullable(null);
		System.out.println("optionalOfNullableBike.isPresent() returns " + optionalOfNullableBike.isPresent());
	}
	private static void emptyOptionals() {
		// Empty Optional - empty container with no object
		Optional<Bike> optionalEmptyBike = Optional.empty();
		// call get() on empty object throws NoSuchElementException
		try {
			Bike emptyBike = optionalEmptyBike.get();
		} catch (java.util.NoSuchElementException e) {
			System.out.println("get() on empty Optional throws java.util.NoSuchElementException " + e.getMessage());
		}
		// isPresent - check if object is empty - but not much advantage over !=
		// null checks
		if (!optionalEmptyBike.isPresent()) {
			System.out.println("isPresent() - ok - but not much improvement on != null");
		}
		// Better Alternatives -
		// orElse - returns a default object if none set
		Bike orElseBike = optionalEmptyBike.orElse(colnagoBike);
		System.out.println("orElse - Optional is empty so return colnagoBike " + orElseBike.getBrand());
		// ifPresent(Consumer<? extends Bike>) - this prints nothing as Optional
		// is empty
		optionalEmptyBike.ifPresent(bike -> System.out.println("ifPresent(Consumer) returns " + bike.getBrand()));
		// orElseThrow - Throw Exception
		try {
			Bike orElseThrowBike = optionalEmptyBike.orElseThrow(NoBikeException::new);
		} catch (NoBikeException nbe) {
			System.out.println("orElseThrow NoBikeException");
		}
	}
}
class Bike {
	private Optional<Wheels> wheels;
	private String brand;
	public Bike(Optional<Wheels> wheels, String brand) {
		this.wheels = wheels;
		this.brand = brand;
	}
	public Optional<Wheels> getWheels() {
		return wheels;
	}
	public void setWheels(Optional<Wheels> wheels) {
		this.wheels = wheels;
	}
	public String getBrand() {
		return brand;
	}
	public void setBrand(String brand) {
		this.brand = brand;
	}
}
class Wheels {
	private String brand;
	private int spokes;
	public Wheels(String brand, int spokes) {
		this.brand = brand;
		this.spokes = spokes;
	}
	public String getBrand() {
		return brand;
	}
	public void setBrand(String brand) {
		this.brand = brand;
	}
	public int getSpokes() {
		return spokes;
	}
	public void setSpokes(int spokes) {
		this.spokes = spokes;
	}
}
class NoBikeException extends Exception {
	private static final long serialVersionUID = 1L;
}
 

 

 

Java 8 – Streams Cookbook

Summary Of Streams

Streams in Java 8 provide a declarative approach to Collections. The simplest analogy is the your Collection is a water butt, and when you turn the tap(faucet) you create a stream which you can then process.

The advantages of Streams are –

  • Declarative
  • Parallelisable
  • Reduced Boilerplate – internal iteration

The Stream operations are either –

  • Intermediate – return streams
  • Terminal – produce result

The final point is that streams can only be traversed once

Cookbook

import java.time.Duration;
import java.util.*;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.*;
public class Winner {
    private int year;
    private String nationality;
    private String name;
    private String team;
    private int lengthKm;
    private Duration winningTime;
    private int stageWins;
    private int daysInYellow;
    
    public Winner(int year, String nationality, String name, String team, int lengthKm, Duration winningTime, int daysInYellow) {
        this.year = year;
        this.nationality = nationality;
        this.name = name;
        this.team = team;
        this.lengthKm = lengthKm;
        this.winningTime = winningTime;
        this.daysInYellow = daysInYellow;
    }
    public static final List<Winner> tdfWinners = Arrays.asList(
            new Winner(2006, "Spain", "Óscar Pereiro", "Caisse d'Epargne–Illes Balears", 3657, Duration.parse("PT89H40M27S"), 8),
            new Winner(2007, "Spain", "Alberto Contador", "Discovery Channel", 3570, Duration.parse("PT91H00M26S"), 4),
            new Winner(2008, "Spain", "Carlos Sastre", "Team CSC", 3559, Duration.parse("PT87H52M52S"), 5),
            new Winner(2009, "Spain", "Alberto Contador", "Astana", 3459, Duration.parse("PT85H48M35S"), 7),
            new Winner(2010, "Luxembourg", "Andy Schleck", "Team Saxo Bank", 3642, Duration.parse("PT91H59M27S"), 12),
            new Winner(2011, "Australia", "Cadel Evans", "BMC Racing Team", 3430, Duration.parse("PT86H12M22S"), 2),
            new Winner(2012, "Great Britain", "Bradley Wiggins", "Team Sky", 3496, Duration.parse("PT87H34M47S"), 14),
            new Winner(2013, "Great Britain", "Chris Froome", "Team Sky", 3404, Duration.parse("PT83H56M20S"), 14),
            new Winner(2014, "Italy", "Vincenzo Nibali", "Astana", 3661, Duration.parse("PT89H59M06S"), 19),
            new Winner(2015, "Great Britain", "Chris Froome", "Team Sky", 3360, Duration.parse("PT84H46M14S"), 16),
            new Winner(2016, "Great Britain", "Chris Froome", "Team Sky", 3529, Duration.parse("PT89H04M48S"), 14 ));
    public static void main(String args[]) {
        // Filter and Map -
        List<String> winnersOfToursLessThan3500km = tdfWinners
                                                        .stream()
                                                        .filter(d -> d.getLengthKm() < 3500) // Separate out Tours less than 3500km
                                                        .map(Winner::getName) // Get names of winners
                                                        .collect(toList()); // Return a list
        // Winners of Tours Less than 3500km - [Alberto Contador, Cadel Evans, Bradley Wiggins, Chris Froome, Chris Froome]        
        System.out.println("Winners of Tours Less than 3500km - " + winnersOfToursLessThan3500km);
        List<String> winnersOfToursGreaterThan3500km = tdfWinners
                                                         .stream()
                                                         .filter(d -> d.getLengthKm() >= 3500)
                                                         .map(Winner::getName)
                                                         .collect(toList());
        // Winners of Tours Greater than 3500km - [Óscar Pereiro, Alberto Contador, Carlos Sastre, Andy Schleck, Vincenzo Nibali, Chris Froome]
        System.out.println("Winners of Tours Greater than 3500km - " + winnersOfToursGreaterThan3500km);
        
        // limit -
        List<Winner> winnerObjectsOfToursLessThan3500kmLimit2 = tdfWinners
                                                                  .stream()
                                                                  .filter(d -> d.getLengthKm() < 3500)
                                                                  .limit(2)
                                                                  .collect(toList());
        // winnerObjectsOfToursLessThan3500kmLimit2 [Alberto Contador, Cadel Evans]
        System.out.println("winnerObjectsOfToursLessThan3500kmLimit2 " + winnerObjectsOfToursLessThan3500kmLimit2);
        
        List<String> firstTwoWinnersOfToursLessThan3500km = tdfWinners
                                                              .stream()
                                                              .filter(d -> d.getLengthKm() < 3500)
                                                              .map(Winner::getName)
                                                              .limit(2)
                                                              .collect(toList());
        // firstTwoWinnersOfToursLessThan3500km - [Alberto Contador, Cadel Evans]
        System.out.println("firstTwoWinnersOfToursLessThan3500km - " + firstTwoWinnersOfToursLessThan3500km);
        // filter by distinct
        List<String> distinctTDFWinners = tdfWinners
                                             .stream()
                                             .map(Winner::getName)
                                             .distinct()
                                             .collect(toList());
        System.out.println("distinctTDFWinners - " + distinctTDFWinners);
        
        
        long numberOfDistinceWinners = tdfWinners
                                          .stream()
                                          .map(Winner::getName)
                                          .distinct()
                                          .count();
        // numberOfDistinceWinners - 8
        System.out.println("numberOfDistinceWinners - " + numberOfDistinceWinners);
        
        // skip records
        List<Winner> skipEveryOtherTDFWinner = tdfWinners
                                                 .stream()
                                                 .skip(2)
                                                 .collect(toList());
        // skipEveryOtherTDFWinner - [Carlos Sastre, Alberto Contador, Andy Schleck, Cadel Evans, Bradley Wiggins, Chris Froome, Vincenzo Nibali, Chris Froome, Chris Froome]
        System.out.println("skipEveryOtherTDFWinner - " + skipEveryOtherTDFWinner);
        
        List<String> mapWinnerYearNamesToList = tdfWinners
                                                   .stream()
                                                   .map(w -> w.getYear() + " - " + w.getName())
                                                   .collect(toList());
        // mapWinnerYearNamesToList [2006 - Óscar Pereiro, 2007 - Alberto Contador, 2008 - Carlos Sastre, 2009 - Alberto Contador, 2010 - Andy Schleck, 2011 - Cadel Evans, 2012 - Bradley Wiggins, 2013 - Chris Froome, 2014 - Vincenzo Nibali, 2015 - Chris Froome, 2016 - Chris Froome]
        System.out.println("mapWinnerYearNamesToList " + mapWinnerYearNamesToList);
        
        List<Integer> mapWinnerNameLengthToList = tdfWinners
                                                    .stream()
                                                    .map(Winner::getName)
                                                    .map(String::length)
                                                    .collect(toList());
        // mapWinnerNameLengthToList [13, 16, 13, 16, 12, 11, 15, 12, 15, 12, 12]
        System.out.println("mapWinnerNameLengthToList " + mapWinnerNameLengthToList);
        
        
        // matching - allMatch, noneMatch
        Optional<Winner> winner2012 = tdfWinners.stream().filter(w -> w.getName().contains("Wiggins")).findAny();
        // winner2012 - Bradley Wiggins
        System.out.println("winner2012 - " + winner2012.get());
        
        Optional<Integer> winnerYear2014 = tdfWinners.stream().map(Winner::getYear).filter(x -> x == 2014).findFirst();
        // winnerYear2014 - 2014
        System.out.println("winnerYear2014 - " + winnerYear2014.get());
        
        
        // reducing - 0 --> initial value
        int totalDistance = tdfWinners.stream().map(Winner::getLengthKm).reduce(0, Integer::sum);
        // totalDistance - 38767
        System.out.println("totalDistance - " + totalDistance);
        
        Optional<Integer> shortestYear = tdfWinners.stream().map(Winner::getLengthKm).reduce(Integer::min);
        // shortestYear - 3360
        System.out.println("shortestYear - " + shortestYear.get());
        
        Optional<Integer> longestYear = tdfWinners.stream().map(Winner::getLengthKm).reduce(Integer::max);
        // longestYear - 3661
        System.out.println("longestYear - " + longestYear.get());
        
        Optional<Winner> fastestWinner = tdfWinners.stream().min(Comparator.comparingDouble(Winner::getAveSpeed));
        System.out.println("fastestTDF - " + fastestWinner.get());
        
        // shorthand
        OptionalDouble fastestTDF = tdfWinners.stream().mapToDouble(Winner::getAveSpeed).min();
        // fastestTDF - 39.0
        System.out.println("fastestTDF - " + fastestTDF.getAsDouble());
        
        
        // groupingby - make a map whose keys are names
        Map<String, List<Winner>> namesVsWinner = tdfWinners.stream().collect(groupingBy(Winner::getName));
        // namesVsWinner - {Bradley Wiggins=[Bradley Wiggins], Carlos Sastre=[Carlos Sastre], Cadel Evans=[Cadel Evans], Óscar Pereiro=[Óscar Pereiro], Chris Froome=[Chris Froome, Chris Froome, Chris Froome], Andy Schleck=[Andy Schleck], Alberto Contador=[Alberto Contador, Alberto Contador], Vincenzo Nibali=[Vincenzo Nibali]}
        System.out.println("namesVsWinner - " + namesVsWinner);
        // join strings
        String allTDFWinnersTeamsCSV = tdfWinners.stream().map(Winner::getTeam).collect(joining(", "));
        // allTDFWinnersTeams Caisse d'Epargne–Illes Balears, Discovery Channel, Team CSC, Astana, Team Saxo Bank, BMC Racing Team, Team Sky, Team Sky, Astana, Team Sky, Team Sky
        System.out.println("allTDFWinnersTeams " + allTDFWinnersTeamsCSV);
        // grouping
        Map<String, List<Winner>> winnersByNationality = tdfWinners.stream().collect(groupingBy(Winner::getNationality));
        // winnersByNationality - {Great Britain=[Bradley Wiggins, Chris Froome, Chris Froome, Chris Froome], Luxembourg=[Andy Schleck], Italy=[Vincenzo Nibali], Australia=[Cadel Evans], Spain=[Óscar Pereiro, Alberto Contador, Carlos Sastre, Alberto Contador]}
        System.out.println("winnersByNationality - " + winnersByNationality);
        Map<String, Long> winsByNationalityCounting = tdfWinners.stream().collect(groupingBy(Winner::getNationality, counting()));
        // winsByNationalityCounting - {Great Britain=4, Luxembourg=1, Italy=1, Australia=1, Spain=4}
        System.out.println("winsByNationalityCounting - " + winsByNationalityCounting);
        
    }
    
    public double getAveSpeed() {
        return (getLengthKm() / (getWinningTime().getSeconds() / 3600) );
    }
    
    public int getYear() {
        return year;
    }
    public void setYear(int year) {
        this.year = year;
    }
    public String getNationality() {
        return nationality;
    }
    public void setNationality(String nationality) {
        this.nationality = nationality;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getTeam() {
        return team;
    }
    public void setTeam(String team) {
        this.team = team;
    }
    public int getLengthKm() {
        return lengthKm;
    }
    public void setLengthKm(int lengthKm) {
        this.lengthKm = lengthKm;
    }
    public Duration getWinningTime() {
        return winningTime;
    }
    public void setWinningTime(Duration winningTime) {
        this.winningTime = winningTime;
    }
    
    public int getStageWins() {
        return stageWins;
    }
    public void setStageWins(int stageWins) {
        this.stageWins = stageWins;
    }
    public int getDaysInYellow() {
        return daysInYellow;
    }
    public void setDaysInYellow(int daysInYellow) {
        this.daysInYellow = daysInYellow;
    }
    @Override
    public String toString() {
        return name;
    }    
    
}

How Lambda’s And Anonymous Inner Classes(AIC) Work

At first glance a lambda looks like a short hand version of an anonymous inner class. But they are not. This post covers the differences between lambda’s and AIC’s

Key Points

  • Lambdas implement a functional interface
  • Anonymous Inner Classes can extend a class or implement an interface with any number of methods
  • Variables – Lambda’s can only access final or effectively final
  • State – Anonymous inner classes can use instance variables so can have state, lambda’s cannot
  • Scope – Lambda part of its enclosing scope – so cant define a variable with same name as variable in enclosing scope
  • Compilation – Anonymous compiles to a class, while lambda is an invokedynamic instruction

How they work

Anonymous Inner Classes(AIC’s)

  • Compiler generates a class file for each anonymous inner class
  • For example – AnonymousInnerClass$1.class
  • Like all classes it needs to be loaded and verified at startup

Lambda

The key to the lambda implementation is the InvokeDynamic instruction introduced in Java 7. This allows dynamic languages to bind to symbol at runtime.

A lambda works like this –

  • Generates invokedynamic call site, and uses a lambdafactory to return the functional implementation
  • lambda convered to a method to be invoked by invokedynamic
  • Method stored in class as private static method
  • Two lambda types – non-capturing – only uses fields inside its body
    – capturing  – accesses fields outside its body

Non-capturing Lambda

Doesnt access fields outside its body

public class NonCapturingLambda {
    public static void main(String[] args) {
        Runnable nonCapturingLambda = () -> System.out.println("NonCapturingLambda");
        nonCapturingLambda.run();
    }
}

If we decode the class file using the cfr decompiler, we see the –

  • LambdaMetafactory
  • Lambda is a static void method in our class
java -jar cfr_0_119.jar NonCapturingLambda --decodelambdas false
/*
 * Decompiled with CFR 0_119.
 */
import java.io.PrintStream;
import java.lang.invoke.LambdaMetafactory;

public class NonCapturingLambda {
    public static void main(String[] args) {
        Runnable nonCapturingLambda = (Runnable)LambdaMetafactory.metafactory(null, null, null, ()V, lambda$0(), ()V)();
        nonCapturingLambda.run();
    }

    private static /* synthetic */ void lambda$0() {
        System.out.println("NonCapturingLambda");
    }
}

Capturing Lambda

Accesses final or effectively final fields outside its body –

public class CapturingLambda {
    public static void main(String[] args) {
        String effectivelyFinal = "effectivelyFinal";
        Runnable capturingLambda = () -> System.out.println("capturingLambda " + effectivelyFinal);
        capturingLambda.run();
    }
}

This decompiles to –

java -jar cfr_0_119.jar CapturingLambda --decodelambdas false
/*
 * Decompiled with CFR 0_119.
 */
import java.io.PrintStream;
import java.lang.invoke.LambdaMetafactory;

public class CapturingLambda {
    public static void main(String[] args) {
        String effectivelyFinal = "effectivelyFinal";
        Runnable capturingLambda = (Runnable)LambdaMetafactory.metafactory(null, null, null, ()V, lambda$0(java.lang.String ), ()V)((String)effectivelyFinal);
        capturingLambda.run();
    }

    private static /* synthetic */ void lambda$0(String string) {
        System.out.println("capturingLambda " + string);
    }
}

The interesting part is the lambda$0 method signature has gone from empty to taking a parameter String

References

https://www.infoq.com/articles/Java-8-Lambdas-A-Peek-Under-the-Hood

http://cr.openjdk.java.net/~briangoetz/lambda/lambda-translation.html

 

 

 

 

 

Another Java Lamdba Post

The syntax of a lambda is simple –

(parameters) -> expression
(parameters) -> { statements; }

Examples

Runnable r1 = () -> System.out.println("Hello World");

// or Streams
List winnersOfToursLessThan3500km = 
                           tdfWinners
                               .stream()
                               .filter(d -> d.getLengthKm() < 3500) // Separate out Tours less than 3500km
                               .map(Winner::getName) // Get names of winners
                               .collect(toList()); // Return a list

Key points are –

  • Concise – Before Java8 we would use anonymous classes to deliver “similar” functionality
  • Anonymous – no explicit name
  • Function – not associated with a particular class
  • Argument – can be passed as argument or Stored in a variable

Functional Interfaces

The key requirement for a lambda is that the interface it implements can only have a Single Abstract Method(SAM). However they can have any number of default and static methods

@FunctionalInterface Annotation

@FunctionalInterface is Optional, and enforces this rule by generating a compiler error –

Invalid '@FunctionalInterface' annotation; NotFunctionalInteface is not a functional interface

Java8 contains a number of useful interfaces in java.util.function –

Predicate   - boolean test(T t) - True/False condition on t
Consumer    - void accept(T t)  - Accepts t but returns no result
Function<T, R> - R apply(T t)      - Takes t and returns an instance of R

Functional Descriptor

Describes the signature of the Functional Interface –

Predicate - t  -> boolean
Consumer  - t  -> void
Function  - t  -> R

Accessing Class Variables

  • final or “effectively final”(not changed after initialization)
        String finalString = "final string";
        String effectivelyFinalString = "effectively final string";
        Runnable r = () -> {
            System.out.println("Hi im " + finalString);
            System.out.println("Hi im " + effectivelyFinalString);
        };
        new Thread(r).start();

But trying to change effectivelyFinalString results stops it compiling –

       String finalString = "final string";
        String effectivelyFinalString = "effectively final string";
        Runnable r = () -> {
            System.out.println("Hi im " + finalString);
            System.out.println("Hi im " + effectivelyFinalString);
        };
        effectivelyFinalString = "now i wont compile";
        new Thread(r).start();

The reason this works is that the lambda is accessing a copy of the final or “effectively final” field.

Method References – ::

The final piece of the lambda jigsaw is Method References. Method references are simply a further shorthand in the body of the lambda – so where we have a lambda –

List winnersOfToursGreaterThan3500km = 
          tdfWinners
             .stream()
             .filter(d -> d.getLengthKm() >= 3500)
             .map(w -> w.getName())
             .collect(toList());

We see map has the lambda – w -> w.getName(). This represents this method –

 Stream map(Function<? super T, ? extends R> mapper);

A method reference lets us shorthand that too –

List winnersOfToursGreaterThan3500km = 
          tdfWinners
             .stream()
             .filter(d -> d.getLengthKm() >= 3500)
             .map(W::getName)
             .collect(toList());

As with a lot of Java8 the purpose of this shorthand is to allow us to write cleaner more concise code

There are 4 types of method reference in Java 8 –

static method ContainingClass::staticMethodName
instance method of a particular object containingObject::instanceMethodName
instance method of an arbitrary object of a particular type ContainingType::methodName
constructor ClassName::new

Google – Site Reliability Engineering

Id previously posted a review of the O’Reilly Site Reliablity Engineering book by Betsy Beyer(Editor) and Chris Jones(Editor). I consider it an important book for any developer or admin to read as it covers googles approach to deploying and scaling their systems. The good news is google have released the book online at Site Reliability Engineering

The book is structured as a series of essays, and the best approach to reading it is to choose the chapters that look like they are most useful to you, and read them. In my case the most relevent chapters were –

  • Structure of Googles Applications
  • Risk and SLA’s
  • Monitoring and Automation

The ultimate aim of an Site Reliability Engineer is that the site should be self managing, and the SRE writes the systems to achieve this.

The most important points I learnt were –

  • Monitoring and Health Checks – They recommend using prometheus.io, and build alerting on top
  • SLA – Does not have to be all encompassing – for example if you cant serve images, but can provide a text based service then you can split the SLA
  • Simplicity – The most important skill a developer can have is to keep it simple

Putting It Into Practice

From my point of view the most important thing to add to my applications was health checks and monitoring. This was easy since most modern frameworks, Spring Boot and dropwizard, already contain health check API’s.

Explaining Functional Programming

It occured to me that while I know what Functional Programming is, I would struggle to explain it. My description would be something like –

You know how Object Oriented Programming is about objects? Well Functional Programming is about functions, you know lambda's, Haskell and Scala

Mmmmnnnn…. not good.

This post is my attempt to provide a better description of functional programming, and let me know any feedback or mistakes

What is Functional Programming?

Functional Programming uses mathematical functions to solve problems. Functions take an input and give an output, without changing the input –

f(x) -> some function of x

Common Features

  • Functions are first class entities – can be assigned to variables, passed as arguments, or returned from other functions
  • No state
  • No side effects – Anything the code does except produce an output from given inputs

Consider the example below the where setting I changes the changeState field, and also log. The are side effects as they go beyond returning an output from an input.

public class SideEffectExample {
   private static final Logger LOGGER = Logger.getLogger(SideEffectExample.class.getName());
   boolean changeState = false;
   int i = 1;
   public int setI(int i) {
       this.i = i;
       this.changeState = true;
       LOGGER.info("change state");
       return i + 1;
   }
}
  • Lazy evaluation – Compiler can decided when best to run a function

The degree to which the above features are enforced depends on the language

Advantages of Functional Programming?

Functional Programming means that a function will give the same output for a given input, and doesnt alter state. This makes it well suited for problems involving –

  • concurrency
  • multi-threading
  • multi-processors

Reference

https://en.wikipedia.org/wiki/Side_effect_%28computer_science%29

1 2 3