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
-
⇒ Coding and Testing the Web Service
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.
-
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);
}
-
A warning appears that the IDE cannot find the class
URL
. Add an import statement forjava.net.URL
, either manually or by pressing Ctrl-Shift-I (⌘-Shift-I on Mac).
-
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 thegetBytes
method.
-
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 thegetFlowerBytes
method and returns anInputStream
. 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 aByteArrayOutputStream
.
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();
}
-
Add import statements for
java.io.InputStream
andjava.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.
-
In the
FlowerService
class body, add the following private method, calledgetImage
. ThegetImage
method’s return type isImage
. The method takes two parameters. The first parameter is a byte array that is created by thegetBytes
method. The second parameter is a boolean that indicates whether the image is a thumbnail. ThegetImage
method throws anIOException
.
private Image getImage(byte[] bytes, boolean isThumbnail) throws IOException {
}
-
In the
getImage
method body, add a line that creates aByteArrayInputStream
from the byte array that the method takes as a parameter.
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
-
Add a line that creates an
Object
from theByteArrayInputStream
.
Object source = bis;
-
Add a line that creates an
ImageInputStream
from the genericObject
.
ImageInputStream iis = ImageIO.createImageInputStream(source);
-
Add a line that creates an
Iterator
of all currently registeredImageReader
s that can decode JPEG files.
Iterator readers = ImageIO.getImageReadersByFormatName("jpeg");
-
Add a line that creates an
ImageReader
from the next element in theIterator
.
ImageReader reader = (ImageReader) readers.next();
-
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);
}
-
Lastly, add code that uses the
ImageReader
object to read theImageInputStream
object and to return anImage
based on that object and the image read parameters.
reader.setInput(iis, true);
return reader.read(0, param);
-
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.
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
-
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"};
-
Add a method that creates an
ArrayList
and adds a byte array for every flower to theList
.
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;
}
-
Add import statements for
java.util.ArrayList
andjava.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:
-
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.
-
Expand the project’s Web Services node. Right-click the FlowerService and select Test Web Service.
-
The web service tester opens in your browser. Type "rose" in the
getFlower
parameter field.
-
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, sincejava.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.
.
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.