End-to-End Binary SOAP Attachment part 3: Coding and Testing the Web Service

This tutorial needs a review. You can edit it in GitHub following these contribution guidelines.

In this lesson you add code to the web service/session bean class to convert JPEG files to byte arrays and byte arrays to java.awt.Image objects. You also add code to the public web service operations so they return these Image objects. Lastly, you test the web service in a browser, using the NetBeans IDE’s Test Web Service utility.

You can download a complete sample of the web service from the NetBeans Samples Catalog.

Lessons In This Tutorial

netbeans stamp 80 74 73
Figure 1. Content on this page applies to the NetBeans IDE 7.2, 7.3, 7.4 and 8.0

Coding the Web Service

You now have a web application containing a set of JPEG files and a web service. The web service is implemented as a stateless session bean. The web service contains two empty web operations. In this lesson you add code to the web service to convert JPEG files to byte arrays and byte arrays to java.awt.Image objects. You also add code to the public web service operations so they return these Image objects.

Get a JPEG File as an Array of Bytes

In this section, you add a pair of private methods to the FlowerService class body. These methods take the name of a flower, create a path to the flower’s JPEG file, and return a binary representation of the JPEG file (an array of bytes). In later sections you add code to the public web service operations so the operations call these private methods.

  1. Open the Source view of the project. You need to add code that takes the name of an image, creates a path to the image based on that name, and retrieves the image as an array of bytes. Type or paste the following code into the FlowerService class body:

private byte[] getFlowerBytes(String name) throws IOException {
    URL resource = this.getClass().getResource("/org/flower/resources/"+name+".jpg");
    return getBytes(resource);
}
  1. A warning appears that the IDE cannot find the class URL . Add an import statement for java.net.URL , either manually or by pressing Ctrl-Shift-I (⌘-Shift-I on Mac).

  1. A new warning appears. The warning states that the IDE cannot find the getBytes method. Left-click the warning icon and click the tip to create the getBytes method.

create method tip
  1. The editor focuses on the getBytes method you just created. Add the following code to the method. This code opens a connection to the URL you passed from the getFlowerBytes method and returns an InputStream . The code then reads the input stream 1024 bytes at a time, stores the bytes in a byte array buffer, and writes from the buffer to a ByteArrayOutputStream .

private byte[] getBytes(URL resource) throws IOException {
    InputStream in = resource.openStream();
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    byte[] buf = new byte[1024];
    for(int read; (read = in.read(buf)) != -1;) {
        bos.write(buf, 0, read);
    }
    return bos.toByteArray();
}
  1. Add import statements for java.io.InputStream and java.io.ByteArrayOutputStream .

Read an Array of Bytes as an Image

In this section, you add a private method to the FlowerService class body. This method takes an array of bytes that represent a JPEG file and returns a java.awt.Image object. Note that the array of bytes is created by the getBytes(URL) method that you created in the section Get a JPEG File as an Array of Bytes.

  1. In the FlowerService class body, add the following private method, called getImage . The getImage method’s return type is Image . The method takes two parameters. The first parameter is a byte array that is created by the getBytes method. The second parameter is a boolean that indicates whether the image is a thumbnail. The getImage method throws an IOException .

private Image getImage(byte[] bytes, boolean isThumbnail) throws IOException {
    }
  1. In the getImage method body, add a line that creates a ByteArrayInputStream from the byte array that the method takes as a parameter.

ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
  1. Add a line that creates an Object from the ByteArrayInputStream .

Object source = bis;
  1. Add a line that creates an ImageInputStream from the generic Object .

ImageInputStream iis = ImageIO.createImageInputStream(source);
  1. Add a line that creates an Iterator of all currently registered ImageReader s that can decode JPEG files.

Iterator readers = ImageIO.getImageReadersByFormatName("jpeg");
  1. Add a line that creates an ImageReader from the next element in the Iterator .

ImageReader reader = (ImageReader) readers.next();
  1. Add lines that create default image read parameters but add 1-in-4 subsampling to the image read parameters if the Image represents a thumbnail.

ImageReadParam param = reader.getDefaultReadParam();
if (isThumbnail) {
    param.setSourceSubsampling(4, 4, 0, 0);
}
  1. Lastly, add code that uses the ImageReader object to read the ImageInputStream object and to return an Image based on that object and the image read parameters.

reader.setInput(iis, true);
return reader.read(0, param);
  1. Press Ctrl-Shift-I (⌘-Shift-I on MacOS). The Fix All Imports dialog opens. Accept the default suggestions of the Fix All Imports dialog and click OK.

fix getimage imports

The getImage method is now complete.

private Image getImage(byte[] bytes, boolean isThumbnail) throws IOException {
    ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
    Object source = bis; // File or InputStream
    ImageInputStream iis = ImageIO.createImageInputStream(source);
    Iterator readers = ImageIO.getImageReadersByFormatName("jpeg");
    ImageReader reader = (ImageReader) readers.next();
    ImageReadParam param = reader.getDefaultReadParam();
    if (isThumbnail) {
        param.setSourceSubsampling(4, 4, 0, 0);
    }
    reader.setInput(iis, true);
    return reader.read(0, param);
}

Implement getFlower

Add the following implementation code to the getFlower() method to get a flower by its name and return the image of that flower, as follows. Note that this code calls the private getFlowerBytes(name) method to get the JPEG file as an array of bytes. The code then calls the private getImage method to return the array of bytes as an Image object.

@WebMethod(operationName = "getFlower")
public Image getFlower(@WebParam(name = "name") String name) throws IOException {
    byte[] bytes = getFlowerBytes(name);
    return getImage(bytes, false);
}

Create a List of Byte Arrays for All JPEG Files

  1. At the top of the class body of FlowerService , create an array of Strings of the names of every flower.

private static final String[] FLOWERS = {"aster", "honeysuckle", "rose", "sunflower"};
  1. Add a method that creates an ArrayList and adds a byte array for every flower to the List .

private List allFlowers() throws IOException {
    List flowers = new ArrayList();
    for (String flower:FLOWERS) {
        URL resource = this.getClass().getResource("/org/flower/resources/"+flower+".jpg");
        flowers.add(getBytes(resource));
    }
    return flowers;
}
  1. Add import statements for java.util.ArrayList and java.util.List .

Implement getThumbnails

Change the getThumbnails() method as follows. Note that you add the implementation code and change the return type from List to List<Image> . Also note that you pass the boolean isThumbnail value of true to the getImage method. The getThumbnails implementation code calls the allFlowers method to create a list of byte arrays for all the JPEG files. The getThumbnails method then creates a List of Image s and calls the getImage method for each flower, to return the array of bytes for that flower as an Image object and add that Image to the List .

@WebMethod(operationName = "getThumbnails")
public List<Image> getThumbnails() throws IOException {
    List<byte[]> flowers = allFlowers();
    List<Image> flowerList = new ArrayList<Image>(flowers.size());
    for (byte[] flower : flowers) {
        flowerList.add(getImage(flower, true));
    }
    return flowerList;
}

The combined web service/session bean is now complete. The final form of the web service class follows:

package org.flower.service;import java.awt.Image;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.ejb.Stateless;
import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;@WebService(serviceName = "FlowerService")
@Stateless()
public class FlowerService {private static final String[] FLOWERS = {"aster", "honeysuckle", "rose", "sunflower"};@WebMethod(operationName = "getFlower")
    public Image getFlower(@WebParam(name = "name") String name) throws IOException {
        byte[] bytes = getFlowerBytes(name);
        return getImage(bytes, false);
    }@WebMethod(operationName = "getThumbnails")
    public List<Image> getThumbnails() throws IOException {
        List flowers = allFlowers();
        List<Image> flowerList = new ArrayList<Image>(flowers.size());
        for (byte[] flower : flowers) {
            flowerList.add(getImage(flower, true));
        }
        return flowerList;
    }private byte[] getFlowerBytes(String name) throws IOException {
        URL resource = this.getClass().getResource("/org/flower/resources/" + name + ".jpg");
        return getBytes(resource);
    }private byte[] getBytes(URL resource) throws IOException {
        InputStream in = resource.openStream();
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        byte[] buf = new byte[1024];
        for (int read; (read = in.read(buf)) != -1;) {
            bos.write(buf, 0, read);
        }
        return bos.toByteArray();
    }private Image getImage(byte[] bytes, boolean isThumbnail) throws IOException {
        ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
        Iterator readers = ImageIO.getImageReadersByFormatName("jpeg");
        ImageReader reader = (ImageReader) readers.next();
        Object source = bis; // File or InputStream
        ImageInputStream iis = ImageIO.createImageInputStream(source);
        reader.setInput(iis, true);
        ImageReadParam param = reader.getDefaultReadParam();
        if (isThumbnail) {
            param.setSourceSubsampling(4, 4, 0, 0);
        }
        return reader.read(0, param);
    }private List allFlowers() throws IOException {
        List flowers = new ArrayList();
        for (String flower : FLOWERS) {
            URL resource = this.getClass().getResource("/flower/album/resources/" + flower + ".jpg");
            flowers.add(getBytes(resource));
        }
        return flowers;
    }
}

Testing the Web Service

Now that the web service is complete, you can deploy and test it.

To test the web service:

  1. Right-click the FlowerAlbumService node and select Deploy. The IDE compiles the source code, launches the GlassFish server, and deploys the project’s WAR file to the server. If you open the Services window, you can see the deployed FlowerService in the server’s Applications node.

Important: The GlassFish Server Open Source Edition must be Version 3.1 or later.

deployed service
  1. Expand the project’s Web Services node. Right-click the FlowerService and select Test Web Service.

test ws node
  1. The web service tester opens in your browser. Type "rose" in the getFlower parameter field.

ws tester
  1. Press the getFlower button. The IDE shows you information about the invocation in the browser. When you look at the "Method Returned", you see that it is garbled. You want to see an image, not a series of symbols. However, since java.awt.Image is not a valid schema type, you need to manually configure the schema file to return binary image/jpeg data. You will do this in the next tutorial.

ws tester badschema

.

Next step:

To send comments and suggestions, get support, and keep informed about the latest developments on the NetBeans IDE Java EE development features, join the nbj2ee@netbeans.org mailing list.