The Java Stream API part 1: the basics

Introduction

Java 8 has a new API called the Stream API. The Stream API, which is represented by the typed interface Stream of T, targets collections. It is a brand new concept in Java and its importance and purpose can be likened to that of LINQ to Collections in .NET. It provides a mechanism to process data in some collection using the MapReduce or Map/Filter/Reduce algorithm.

Short summary of MapReduce

MapReduce is eagerly used in data mining and big data applications to find information from a large, potentially unstructured data set. Don’t worry, we won’t need any big data cluster to test the Stream API as even the smallest collections can be analysed. E.g. finding the average age of all Employees who have been employed for more than 5 years is a good candidate for the Stream API.

The Stream API introduces automatic parallelism in the computations without us having to write any extra technical code. We can avoid tedious intermediary stages, like looping through all employees to find the ones who have spent more than 5 years at the company and then calculating the average on them. That is an important goal of the Stream API, i.e. to avoid intermediary results and collections for the computations.

The individual parts of Map/Filter/Reduce, i.e. the Map, the Filter and the Reduce are steps or operations in a chain to compute something from a collection. Not all 3 steps are required in all data mining cases. Examples:

  • Finding the average age of employees who have been working at a company for more than 5 years: you map the age property of each employee to a list of integers but filter out those who have been working for less than 5 years. Then you calculate the average of the elements in the integer list, i.e. reduce the list to a single outcome.
  • Finding the ids of every employee: if the IDs are strings then you can map the ID fields into a list of strings, there’s no need for any filtering or reducing.
  • Finding the average age of all employees: you map the age of each employee into an integer list and then calculate the average of those integers in the reduce phase, there’s no need for filtering
  • Find all employees over 50 years of age: we filter out the employees who are younger than 50, there’s no need for mapping or reducing the employees collection.

MapReduce implementations in reality can become quite complex depending on the query and structure of the source data. We won’t go into those at all – I couldn’t even if I wanted to as large-scale data mining is not exactly my specialty.

A Stream is an object that will represent one such step in the algorithm. Although Streams operate on Collections, a Stream is NOT a collection. A Stream will not hold any data in the same sense as a Java collection holds data. Also, a Stream should not change the source data in any way, i.e. the collection that the Stream operates on, will remain untouched by the Stream. Keep in mind though, that the Stream steps are carried out in parallel, so it’s vital that they work on the same data otherwise you’ll get unpredictable results.

First example

Enough of the theory, let’s see some code. The easiest way to create a stream is to call the stream() method on a Collection such as a List. Recall from the posts on lambda expressions how we defined a forEach loop on a list of strings. We’ll first add the names of the employees to a string list in the old way and the print the names according to the new Lambda way:

List<String> names = new ArrayList<>();
for (Employee employee : companyEmployees)
{
       names.add(employee.getName());
}
Consumer<String> printConsumer = System.out::println;
names.forEach(printConsumer);

Read further on for a reminder on the Employee class.

The forEach method is also available on a Stream so the below code will perform the same:

Consumer<String> printConsumer = System.out::println;
Stream<String> stream = names.stream();
stream.forEach(printConsumer);

A Stream has a lot more interesting functions of course. It’s those functions where the new java.util.function functional interfaces will come in handy. If you don’t know what that package does then read through the posts on lambda expressions in Java referred to above.

Let’s revisit our Employee class for the next examples:

public class Employee
{
    private UUID id;
    private String name;
    private int age;

    public Employee(UUID id, String name, int age)
    {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    public UUID getId()
    {
        return id;
    }

    public void setId(UUID id)
    {
        this.id = id;
    }

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }    
    
    public int getAge()
    {
        return age;
    }

    public void setAge(int age)
    {
        this.age = age;
    }
}

…and we have the following collection:

List<Employee> employees = new ArrayList<>();
employees.add(new Employee(UUID.randomUUID(), "Elvis", 50));
employees.add(new Employee(UUID.randomUUID(), "Marylin", 18));
employees.add(new Employee(UUID.randomUUID(), "Freddie", 25));
employees.add(new Employee(UUID.randomUUID(), "Mario", 43));
employees.add(new Employee(UUID.randomUUID(), "John", 35));
employees.add(new Employee(UUID.randomUUID(), "Julia", 55));        
employees.add(new Employee(UUID.randomUUID(), "Lotta", 52));
employees.add(new Employee(UUID.randomUUID(), "Eva", 42));
employees.add(new Employee(UUID.randomUUID(), "Anna", 20));

Say we need to find all employees aged 50 and above:

Stream<Employee> stream = employees.stream();
Stream<Employee> fiftyAndAbove = stream.filter(emp -> emp.getAge() >= 50);

The filter() method of a Stream accepts a Predicate of T – Employee in this case – which will return true if the age of the employee is at least 50. Predicates can be chained with the “and”, “or” and “negate” default methods available in the Predicate interface:

Stream<Employee> stream = employees.stream();
        
Predicate<Employee> fiftyAndBelow = emp -> emp.getAge() <= 50;
Predicate<Employee> olderThanTwenty = emp -> emp.getAge() > 20;
Predicate<Employee> startsWithE = emp -> emp.getName().startsWith("E");
        
Predicate<Employee> joined = fiftyAndBelow.and(olderThanTwenty).and(startsWithE.negate());
        
Stream<Employee> filtered = stream.filter(joined);

Here we want to collect all Employees older than 20, at most 50 and whose name doesn’t start with an ‘E’.

You can create arbitrary Streams using the static “of” method of Stream:

Stream<Integer> of = Stream.of(1, 2, 4, 2, 10, 4, 40);
Predicate<Integer> pred = Predicate.isEqual(4);
Stream<Integer> filter = of.filter(pred);

Here we have a stream of integers and we want to collect the ones that are equal to 4.

If you’d like to see the contents of the stream “filter” then you can call the forEach method on it:

filter.forEach(System.out::println);

…which will correctly output 4 and 4, i.e. the two elements from stream “of” that are equal to 4.

OK, but how can we access the filtered elements? How can we look at the result of the query? We’ll see that in the next post.

View all posts related to Java here.

Default interface functions in Java 8

Introduction

A new feature in Java 8 is default function implementations. They are default implementations of methods of an interface. Default methods can help extending an interface without breaking the existing implementations. After all if you add a new method to an interface then all implementing types must handle it otherwise the compiler will complain.

This can be cumbersome if your interface has a large number of consumers. You’ll break their code and they will need to implement the new function – which they might not even need.

The default keyword for interfaces

In .NET the above problem can be easily solved by extension methods. There’s no equivalent of extension methods in Java – at least not that I know of – but it’s possible to approximate them using the ‘default’ keyword within an interface. Let’s say I have the following interface:

public interface ISomeInterface
{
    void doSomething();
    int countSomething();
    void shadyFunction();
}

Then an implementing class must include all of these otherwise you get a compiler error:

public class SomeImplementor implements ISomeInterface
{

    @Override
    public void doSomething()
    {
        System.out.println("Hello world");
    }

    @Override
    public int countSomething()
    {
        return 1000;
    }

    @Override
    public void shadyFunction()
    {
        System.out.println("Let's relocate to Mars");
    }
    
}

This is extremely basic, right? Now, what if you want to extend ISomeInterface without breaking SomeImplementor? Up until Java 7 this wan’t an option, but in Java 8 it’s possible as follows:

public interface ISomeInterface
{
    void doSomething();
    int countSomething();
    void shadyFunction();
    
    default void incredibleFunction(String message)
    {
        System.out.println(message);
    }
}

The compiler won’t complain that there’s no “incredibleFunction” implementation in SomeImplementor. You can still override it of course but you’re free to call the function from an instance of SomeImplementor:

SomeImplementor si = new SomeImplementor();
si.incredibleFunction("Fantastic!");

So the ‘default’ keyword in interfaces lets you provide a default implementation of a method without forcing the implementing classes to provide their own implementation. This is quite useful: you can extend an interface without worrying about the existing implementations.

We can see examples of default implementations throughout the new java.util.function interfaces. Predicate of T, i.e. a function that returns boolean and accepts one input parameter has an “and” default method which allows you to chain boolean operations that must be evaluated together:

Predicate<String> stringConditionOne = s -> s.length() > 20;
Predicate<String> stringConditionTwo = s -> s.contains("search");
        
Predicate<String> combinedPredicate = stringConditionOne.and(stringConditionTwo);

The default “and” implementation of the Predicate interface will simply test both conditions and return true if both evaluate to true.

The Predicate interface also has a default static “isEqual” method whose implementation simply calls the equals method of Object if the input parameter is not null:

Predicate<String> equal = Predicate.isEqual("hello");
boolean test = equal.test("hello");

Here “test” will be true.

View all posts related to Java here.

Lambda expressions in Java 8 part 2: extended syntax and the function package

Introduction

In the previous post in this short series we introduced the syntax of lambda expressions in Java 8. In this post we’ll look at a couple more facets of lambda expressions in Java: the ‘::’ operator and the new java.util.function package.

Syntactic sugar with ‘::’

There’s a new operator in Java 8: ‘::’, i.e. a double-colon. It’s used as a shortcut to write lambda expressions. Recall our Comparator implementation from the previous post:

Comparator<Employee> employeeAgeComparator = 
                (employeeOne, employeeTwo) -> Integer.compare(employeeOne.getAge(), employeeTwo.getAge());

That was an Employee comparison where the input parameters were of type Employee but we compared their ages which are of type Integer. Say that we first collect the age values into a separate integer list. We can then write a pure integer comparator in a very similar way:

Comparator<Integer> intComparator = (int1, int2) -> Integer.compare(int1, int2);

This can be rewritten as follows:

Comparator<Integer> intComparatorShort = Integer::compare;

This way of writing the lambda expression is called a method reference. We first write the object on which we want to invoke a method, i.e. “Integer”, followed by a double-colon, and finally we have the name of the method. The compiler will infer from the Comparator type that we want to compare two integers so we don’t need to write compare(int1, int2). We’ll see other examples of this later on but the difference between this syntax and the one we saw in the previous post is purely syntactic. There’s no performance gain or loss with either of them.

java.util.function

Java.util.function is a new package that provides a range of functional interfaces. If you work in an IDE which provides intellisense – such as NetBeans – then you can type “import java.util.function.” above a class declaration to see the list of interfaces within this package. You’ll see names such as…

BiConsumer<T, U>
Consumer<T>
LongSupplier

At first these interfaces probably look quite strange. They are out-of-the box functional interfaces that represent some frequently used methods so that they can be written as lambda expressions. Examples:

  • BiConsumer of T and U: represents a void method that accepts two arguments of types T and U
  • Consumer of T: same as BiConsumer but it accepts a single parameter only
  • IntSupplier: a method that returns an integer and accepts no arguments
  • BiPredicate of T and U: a function that returns a boolean and accepts two arguments
  • Function of T and R: a function that accepts an argument of type T and returns and object of type R

The input and output parameter types can be the same or different.

There are also specialised interfaces such as the UnaryOperator of T which extends Function of T and T. This means that UnaryOperator is a Function which returns an object of type T and returns an object of type T, i.e. both the input and output parameters are of the same type.

A simple example is System.out.println(String s). This is a void method that accepts a single argument of String, i.e. this fits the functional interface type of Consumer of String:

Consumer<String> systemPrint = s -> System.out.println(s);

We know from the above section that we can shorten this code to the following:

Consumer<String> systemPrint = System.out::println;

The Comparator of integers we saw above accepts two integers and returns another integer. This sounds like a BiFunction of int, int, int, i.e. a function that accepts 2 integers and returns another integer:

BiFunction<Integer, Integer, Integer> intComparatorFunctional = (t, t1) -> Integer.compare(t, t1);

…and as all types are the same we can use the shorthand notation:

BiFunction<Integer, Integer, Integer> intComparatorFunctional = Integer::compare;

We can further simplify this as there’s a specialised functional interface for the case of two integer inputs and one integer return value: IntBinaryOperator. The shortened version of the integer comparator looks like this:

IntBinaryOperator intComparatorAsBinaryOperator = Integer::compare;

So if you see that all parameters are of the same type then it’s worth checking what’s available in the java.util.function package because there might be a specialised interface. Choose the one that you think is most straightforward.

You can use these interfaces to pass around lambda expressions as input parameters. E.g. there’s a new method available for Collections, or objects that implement the Iterable interface to be exact: forEach, which accepts a Consumer of T. In other words you can iterate through the items in a collection and pass in a Consumer, i.e. a void method which accepts a single parameter to perform some action on each item in a collection in a single statement:

stringList.forEach(s -> System.out.println(s));

…or…:

stringList.forEach(System.out::println);

Other examples:

Add the items of a list to Employee objects to another list – we saw the Employee object in the previous post:

List<Employee> employees = new ArrayList<>();
        List<Employee> employeesCopy = new ArrayList<>();
        employees.add(new Employee(UUID.randomUUID(), "Elvis", 50));
        employees.add(new Employee(UUID.randomUUID(), "Marylin", 18));
        employees.add(new Employee(UUID.randomUUID(), "Freddie", 25));
        employees.add(new Employee(UUID.randomUUID(), "Mario", 43));
        employees.add(new Employee(UUID.randomUUID(), "John", 35));
        employees.add(new Employee(UUID.randomUUID(), "Julia", 55));        
        employees.add(new Employee(UUID.randomUUID(), "Lotta", 52));
        employees.add(new Employee(UUID.randomUUID(), "Eva", 42));
        employees.add(new Employee(UUID.randomUUID(), "Anna", 20));   
        
        Consumer<Employee> copyEmployees = employeesCopy::add;
        employees.forEach(copyEmployees);

employeesCopy will have the same objects as the employees list.

You can even chain Consumers with the “andThen” interface method:

Consumer<Employee> copyEmployees = employeesCopy::add;
Consumer<Employee> printEmployeeName = (Employee e) -> System.out.println(e.getName());
employees.forEach(copyEmployees.andThen(printEmployeeName));

View all posts related to Java here.

Lambda expressions in Java 8 part 1: basic syntax

Introduction

If you’re familiar with .NET then you already know what Lambda expressions are and how useful they can be. They were not available in Java before version 8. Let’s investigate how they can be applied in Java.

First example: an interface method with a single parameter

Say you have the following Employee class:

public class Employee
{
    private UUID id;
    private String name;
    private int age;

    public Employee(UUID id, String name, int age)
    {
        this.id = id;
        this.name = name;
        this.age = age;
    }
        
    public UUID getId()
    {
        return id;
    }

    public void setId(UUID id)
    {
        this.id = id;
    }

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }    
    
    public int getAge()
    {
        return age;
    }

    public void setAge(int age)
    {
        this.age = age;
    }
}

You can judge whether or not an Employee is cool based on a number of factors. As the implementation of “coolness” can vary so let’s hide it behind an interface:

public interface EmployeeCoolnessJudger
{
    boolean isCool(Employee employee);
}

Here comes an anonymous implementation of the EmployeeCoolnessJudger interface based on the employee name. We simply say that everyone with the name “Elvis” is cool:

EmployeeCoolnessJudger nameBasedCoolnessJudger = new EmployeeCoolnessJudger()
{
            @Override
            public boolean isCool(Employee employee)
            {
                return employee.getName().equals("Elvis");
            }
};

In Java 8 this can be rewritten as follows:

EmployeeCoolnessJudger nameBasedCoolnessJudgerAsLambda = 
                (Employee employee) -> employee.getName().equals("Elvis");

If you know lambdas from .NET then this will look very familiar to you. We declare the input parameters within brackets to the isCool method. As the interface has only one method it’s not necessary to show its name anywhere, the compiler will “understand”. The parameter declaration is followed by a dash ‘-‘ and the greater-than sign, which is similar to ‘=>’ in .NET. Then we write what we want the function to return which will be a boolean. Note that we don’t need the return statement. Also, as the whole method implementation fits into a single line we didn’t need any curly braces.

The parameter type can in fact be omitted, which is again similar to .NET:

EmployeeCoolnessJudger nameBasedCoolnessJudgerAsLambda = 
                (employee) -> employee.getName().equals("Elvis");

…and if there’s only one parameter then the brackets can be omitted as well:

EmployeeCoolnessJudger nameBasedCoolnessJudgerAsLambda = 
                employee -> employee.getName().equals("Elvis");

How can we use this lambda implementation of EmployeeCoolnessJudger? You can pass it around like any other object. Say the Employee class has a function that accepts an EmployeeCoolnessJudger:

public boolean isCool(EmployeeCoolnessJudger coolnessJudger)
{
     return coolnessJudger.isCool(this);
}

Then you can construct an Employee object and pass the lambda expression name into the isCool method:

Employee coolEmployee = new Employee(UUID.randomUUID(), "Elvis", 50);
boolean isCool = coolEmployee.isCool(nameBasedCoolnessJudgerAsLambda);

…or you can pass the complete Lambda expression into the function…:

Employee coolEmployee = new Employee(UUID.randomUUID(), "Elvis", 50);
boolean isCool = coolEmployee.isCool(employee -> employee.getName().equals("Elvis"));

…which returns true as expected.

Second example: an interface with no parameters

The above example required a single parameter. How is the syntax affected if there are no parameters? Say that we want an employee to say something. Again, we can hide the implementation behind an interface:

public interface EmployeeSpeaker
{
    void speak();
}

We can implement an anonymous method of this to say “Hello World”:

EmployeeSpeaker helloWorldSpeaker = new EmployeeSpeaker()
{

            @Override
            public void speak()
            {
                System.out.println("I'm saying Hello World!");
            }
};

The anonymous helloWorldSpeaker implementation can be rewritten with a Lambda expression as follows:

EmployeeSpeaker helloWorldSpeaker = () ->  System.out.println("I'm saying Hello World!");

As the implementation doesn’t require any input parameters it’s enough to write empty brackets followed by dash and greater-than. If the method body spans more than one line of code we’ll need to put them within curly braces:

EmployeeSpeaker helloWorldSpeaker = () ->
        { 
            String sentence = "I'm saying Hello World!";
            System.out.println(sentence);        
        };

The usage is the same as above. The employee class can have a method that accepts an EmployeeSpeaker as input parameter:

public void saySomething(EmployeeSpeaker speaker)
    {
        speaker.speak();
    }

You can call it as follows:

coolEmployee.saySomething(helloWorldSpeaker);

…which will print “I’m saying Hello World!” to some console depending on the IDE you’re using.

Third example: an interface with 2 or more parameters

We want to compare the Employee objects based on their ages and sort them accordingly. One way to achieve this is to implement the generic Comparator interface. Say we have the following employees:

List<Employee> employees = new ArrayList<>();
        employees.add(new Employee(UUID.randomUUID(), "Elvis", 50));
        employees.add(new Employee(UUID.randomUUID(), "Marylin", 18));
        employees.add(new Employee(UUID.randomUUID(), "Freddie", 25));
        employees.add(new Employee(UUID.randomUUID(), "Mario", 43));
        employees.add(new Employee(UUID.randomUUID(), "John", 35));
        employees.add(new Employee(UUID.randomUUID(), "Julia", 55));        
        employees.add(new Employee(UUID.randomUUID(), "Lotta", 52));
        employees.add(new Employee(UUID.randomUUID(), "Eva", 42));
        employees.add(new Employee(UUID.randomUUID(), "Anna", 20));   

Here comes the anonymous class solution to implement Comparator of Employee:

Comparator<Employee> employeeAgeComparator = new Comparator<Employee>()
        {

            @Override
            public int compare(Employee employeeOne, Employee employeeTwo)
            {
                return Integer.compare(employeeOne.getAge(), employeeTwo.getAge());
            }
        };

…and here comes the lambda solution. Note that we have 2 input parameters:

Comparator<Employee> employeeAgeComparator = 
      (Employee employeeOne, Employee employeeTwo) -> Integer.compare(employeeOne.getAge(), employeeTwo.getAge());

…or without specifying the parameter types:

Comparator<Employee> employeeAgeComparator = 
                (employeeOne, employeeTwo) -> Integer.compare(employeeOne.getAge(), employeeTwo.getAge());

As we have more than one input parameters we cannot leave off the brackets.

We can use the custom comparator as follows:

Collections.sort(employees, employeeAgeComparator);
        
for (Employee employee : employees)
{
       System.out.println(employee.getName());
}

This prints out the names as follows:

Marylin
Anna
Freddie
John
Eva
Mario
Elvis
Lotta
Julia

Some things to note

Lambdas in Java also introduced a couple of new concepts::

  • The type definition of a Lambda expression is functional interface. Such an interface type can only have one abstract method.
  • You can use the @FunctionalInterface annotation to annotate functional interfaces if you prefer to be explicit about it, see example below
  • Lambda expressions can be used as variables and passed into other methods. We’ve seen examples of that above: nameBasedCoolnessJudgerAsLambda and employeeAgeComparator. As a consequence a Lambda expression can be returned by a method as well. E.g. nameBasedCoolnessJudger can be returned from a method whose return type is EmployeeCoolnessJudger
  • Creating Lambdas doesn’t involve as much overhead as creating an anonymous object with the “new” keyword so you can speed up the application by lambdas.

Here’s an example of the FunctionalInterface annotation:

@FunctionalInterface
public interface ISomeFunctionalInterface
{
    void doSomething(String param);
}

As soon as you try to add another abstract method to this interface you’ll get a compiler error:

@FunctionalInterface
public interface ISomeFunctionalInterface
{
    void doSomething(String param);
    int returnSomething();
}

…:

error: Unexpected @FunctionalInterface annotation
@FunctionalInterface
ISomeFunctionalInterface is not a functional interface
multiple non-overriding abstract methods found in interface ISomeFunctionalInterface

We’ll continue with terminal and intermediary operations in the next post.

View all posts related to Java here.

How to post a Multipart http message to a web service in C# and handle it with Java

This post is going to handle the following scenario:

  • Upload a file to a server by sending an HTTP POST to a web service in a multipart form data content type with C#
  • Accept and handle the message in the web service side using Java

I admit this may not be the typical scenario you encounter in your job as a .NET developer; however, as I need to switch between the .NET and the Java world relatively frequently in my job this just happened to be a problem I had to solve recently.

Let’s start with the .NET side of the problem: upload the byte array contents of a file to a server using a web service. We’ll take the following steps:

  • Read in the byte array contents of the file
  • Construct the HttpRequestMessage object
  • Set up the request message headers
  • Set the Multipart content of the request
  • Send the request to the web service
  • Await the response

Start Visual Studio 2012 – the below code samples should work in VS2010 as well – and create a new Console application. We will only work within Program.cs for simplicity.

Step 1: read the file contents, this should be straightforward

private static void SendFileToServer(string fileFullPath)
        {
            FileInfo fi = new FileInfo(fileFullPath);
            string fileName = fi.Name;
            byte[] fileContents = File.ReadAllBytes(fi.FullName);
        }

Step2: Construct the HttpRequestMessage object

The HttpRequestMessage within the System.Net.Http namespace represents exactly what it says: a HTTP request. It is a very flexible object that allows you to specify the web method, the contents, the headers and much more properties of the HTTP message. Add the following code to SendFileToServer(string fileFullPath):

Uri webService = new Uri(@"http://avalidwebservice.com");
HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, webService);
requestMessage.Headers.ExpectContinue = false;

The last piece of code, i.e. the one that sets ExpectContinue to false means that the Expect header of the message will not contain Continue. This property is set to true by default. However, a number of servers don’t know how to handle the ‘Continue’ value and they will throw an exception. I ran into this problem when I was working on this scenario so I’ll set it to false. This does not mean that you have to turn off this property every time you call a web service with HttpRequestMessage, but in my case it solved an apparently inexplicable problem.

You’ll obviously need to replace the fictional web service address with a real one.

Step 3: set the multipart content of the http request

You should specify the boundary string of the multipart message in the constructor of the MultipartFormDataContent object. This will set the boundary of the individual parts within the multipart message. We’ll then add a byte array content to the message passing in the bytes of the file to be uploaded. Note that we can add the following parameters to the to individual multipart messages:

  • The content itself, e.g. the byte array content
  • A name for that content: this is ideal if the receiving party needs to search for a specific name
  • A filename that will be added to the content-disposition header of the message: this is a name by which the web service can save the file contents

We also specify that the content type header should be of application/octet-stream for obvious reasons.

Add the following code to SendFileToServer(string fileFullPath):

MultipartFormDataContent multiPartContent = new MultipartFormDataContent("----MyGreatBoundary");
ByteArrayContent byteArrayContent = new ByteArrayContent(fileContents);
byteArrayContent.Headers.Add("Content-Type", "application/octet-stream");
multiPartContent.Add(byteArrayContent, "this is the name of the content", fileName);
requestMessage.Content = multiPartContent;

Step 4: send the message to the web service and get the response

We’re now ready to send the message to the server by using the HttpClient object in the System.Net.Http namespace. We’ll also get the response from the server.

HttpClient httpClient = new HttpClient();
Task<HttpResponseMessage> httpRequest = httpClient.SendAsync(requestMessage,    HttpCompletionOption.ResponseContentRead, CancellationToken.None);
HttpResponseMessage httpResponse = httpRequest.Result;

We can send the message using the SendAsync method of the HttpClient object. It returns a Task of type HttpResponseMessage which represents a Task that will be carried out in the future. Note that this call will NOT actually send the message to the service, this is only a preparatory phase. If you are familiar with the Task Parallel Library then this should be no surprise to you – the call to the service will be made upon calling the Result property of the Task object.

This post is not about the TPL so I will not go into any details here – if you are not familiar with the TPL but would like to learn about multipart messaging then read on and please just accept the provided code sample ‘as is’. Otherwise there are a great number of sites on the net discussing the Task object and its workings.


Step 5
: read the response from the server

Using the HttpResponseMessage object we can analyse the service response in great detail: status code, response content, headers etc. The response content can be of different types: byte array, form data, string, multipart, stream. In this example we will read the string contents of the message, again using the TPL. Add the following code to SendFileToServer(string fileFullPath):

HttpStatusCode statusCode = httpResponse.StatusCode;
                HttpContent responseContent = httpResponse.Content;

                if (responseContent != null)
                {
                    Task<String> stringContentsTask = responseContent.ReadAsStringAsync();
                    String stringContents = stringContentsTask.Result;                    
                }

It is up to you of course what you do with the string contents.

Ideally we should include the web service call in a try-catch as service calls can throw all sorts of exceptions. Here the final version of the method:

private static void SendFileToServer(string fileFullPath)
        {
            FileInfo fi = new FileInfo(fileFullPath);
            string fileName = fi.Name;
            byte[] fileContents = File.ReadAllBytes(fi.FullName);
            Uri webService = new Uri(@"http://avalidwebservice.com");
            HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, webService);
            requestMessage.Headers.ExpectContinue = false;

            MultipartFormDataContent multiPartContent = new MultipartFormDataContent("----MyGreatBoundary");
            ByteArrayContent byteArrayContent = new ByteArrayContent(fileContents);
            byteArrayContent.Headers.Add("Content-Type", "application/octet-stream");
            multiPartContent.Add(byteArrayContent, "this is the name of the content", fileName);
            requestMessage.Content = multiPartContent;

            HttpClient httpClient = new HttpClient();
            try
            {
                Task<HttpResponseMessage> httpRequest = httpClient.SendAsync(requestMessage, HttpCompletionOption.ResponseContentRead, CancellationToken.None);
                HttpResponseMessage httpResponse = httpRequest.Result;
                HttpStatusCode statusCode = httpResponse.StatusCode;
                HttpContent responseContent = httpResponse.Content;

                if (responseContent != null)
                {
                    Task<String> stringContentsTask = responseContent.ReadAsStringAsync();
                    String stringContents = stringContentsTask.Result;                    
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

This concludes the .NET portion of our problem. Let’s now see how the incoming message can be handled in a Java web service.

So you have a Java web service which received the above multipart message. The solution presented below is based on a Servlet with the standard doPost method.

The HttpServletRequest in the signature of the doPost method can be used to inspect the individual parts of the incoming message. This yields a collection which we can iterate through:

@Override
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        Collection<Part> requestParts = request.getParts();
        Iterator<Part> partIterator = requestParts.iterator();
        while (partIterator.hasNext())
        {
        }
    }

If the message is not of type MultipartFormData then the collection of messages will be zero length.

The Part object in the java.servlet.http namespace represents a section in the multipart message delimited by some string token, which we provided in the MultipartFormDataContent constructor. Now our goal is to specifically find the byte array message we named “this is the name of the content” in the .NET code. This name can be extracted using the getName() getter of the Part object. Add the following code to the while loop:

Part actualPart = partIterator.next();
if (actualPart.getName().equals("this is the name of the content"))
{
}

The Part object also offers a getInputStream() method that can be used later to save the byte array in a file. The file name we provided in the C# code will be added to the content-disposition header of the multipart message – or to be exact to the header of the PART of the message. Keep in mind that each individual message within the multipart message can have its own headers. We will need to iterate through the headers of the byte array message to locate the content-disposition header. Add the following to the if clause:

InputStream is = actualPart.getInputStream();
String fileName = "";
Collection<String> headerNames = actualPart.getHeaderNames();
Iterator<String> headerNamesIterator = headerNames.iterator();
while (headerNamesIterator.hasNext())
{
    String headerName = headerNamesIterator.next();
    String headerValue = actualPart.getHeader(headerName);
    if (headerName.equals("content-disposition"))
    {
    }
}

The last step of the problem is to find the file name within the header. The value of the content-disposition header is a collection of comma separated key-value pairs. Within it you will find “filename=myfile.txt” or whatever file name was provided in the C# code. I have not actually found any ready-to-use method to extract exactly the filename so my solution is very a very basic one based on searching the full string. Add the below code within “if (headerName.equals(“content-disposition”))”:

String searchTerm = "filename=";
int startIndex = headerValue.indexOf(searchTerm);
int endIndex = headerValue.indexOf(";", startIndex);
fileName = headerValue.substring(startIndex + searchTerm.length(), endIndex);

So now you have access to all three ingredients of the message:

  • The byte array in form of an InputStream object
  • The name of the byte array contents
  • The file name

The next step would be to save the message in the file system, but that should be straightforward using the ‘read’ method if the InputStream:

OutputStream out = new FileOutputStream(f);
byte buf[] = new byte[1024];
int len;
while ((len = is.read(buf)) > 0)
{
    out.write(buf, 0, len);
}

…where ‘is’ is the InputStream presented above and ‘f’ is a File object where the bytes will be saved.

View the list of posts on Messaging here.