FeaturesPluginsDocs & SupportCommunityPartners

End-to-End Web Service Tutorial: Flower Application

In this tutorial, you first create an EJB module containing a session bean that makes images available. Next, you create a web application that contains a web service, which delegates to the EJB module to retrieve the images. The web service exposes methods that can be used by clients to access the images provided by the EJB module. Then you deploy the web application and the EJB module together, as a unit, by adding them to an enterprise application and then deploying the enterprise application. At this stage, you are introduced to GlassFish testing functionality that is available from the IDE. Finally, you create a Java application that connects to the web service to display the images in an album created from Swing components. In the concluding section, you are also shown how to optimize the transfer of images from web services to clients.

Contents

Content on this page applies to NetBeans IDE 6.0

To follow this tutorial, you need the following software and resources.

Software or Resource Version Required
NetBeans IDE Web & Java EE version 6.0
Java Development Kit (JDK) version 6 or
version 5
Java EE-compliant web or application server Tomcat web server 6.0 and/or
GlassFish application server v2
Pictures used in this tutorialrose.jpg
sunflower.jpg
aster.jpg honeysuckle.jpg

Both Tomcat and GlassFish can be installed with the Web and Java EE distribution of NetBeans IDE. Alternatively, you can visit the GlassFish downloads page or the Apache Tomcat downloads page.

Optionally, for troubleshooting purposes, you can download the completed sample and inspect the sources.

At the end of this tutorial, you will have a running Java Swing application that consumes the EJB module's images via a web service, with this result: Java application with consumed ws

Creating the EJB Module

The goal of this section is to create an EJB module that exposes two methods, the first for providing a single image, the second for providing all the images. Normally, the images would come from a database. Since database retrieval is not the focus of this tutorial, we simply place the images in a resource folder within our EJB module.

  1. Choose File > New Project (Ctrl-Shift-N). The New Project wizard appears. Select EJB Module from the Enterprise category, as below:
    Java application with consumed ws

    Click Next.

  2. Type FlowerAlbum in Project Name, as shown below:
    Java application with consumed ws

    Click Finish.

    You now have an EJB module project that looks like this in the Projects window:
    Java application with consumed ws

  3. Right-click the FlowerAlbum project node and choose New > Session Bean. Alternatively, right-click the project node and choose New > Other. In the New File wizard, choose Session Bean under Enterprise, as shown here:
    Java application with consumed ws

    The New Session Bean wizard appears.

  4. Name the session bean Flower, together with flower.album as the package name. Make sure to select Stateless and Remote. You should now see the following:
    Java application with consumed ws

    Click Finish.

    The IDE adds a session bean to the Source Packages node, together with a remote interface, as shown here. In the Enterprise Beans node, a new node is added for your new FlowerBean:
    Java application with consumed ws

  5. Expand the Enterprise Beans node, right-click the FlowerBean node, and choose Add > Business Method, as shown here:
    Java application with consumed ws

    Type the following values in the Business Method dialog:

    • Name: getFlower
    • Return Type: byte[]

    Click Add. In Name, type name. Leave the other values unchanged. You should now see the following:
    Java application with consumed ws

    Click the Exceptions tab. Click Add. Type IOException. You should now see the following:
    Java application with consumed ws

    Click OK. You now have the basis of a method in your bean class, and a method declaration in the remote interface class.

  6. Call up the Business Method dialog again. This time, enter the following values:
    • Name: allFlowers
    • Return Type: List<byte[]>

    You should now see the following:


    Java application with consumed ws

    As before, add IOException to the Exceptions tab.

    Click OK.

  7. In the remote interface class, notice that the methods have successfully been generated by the previous steps:
    @Remote
    public interface FlowerRemote {
    
        byte[] getFlower(String name) throws IOException;
    
        List<byte[]> allFlowers() throws IOException;
    
                }

    Look in the bean class and notice that stubs have been created for the declared methods:

    @Stateless
    public class FlowerBean implements FlowerRemote {
    
        public byte[] getFlower(String name) throws IOException {
            return null;
        }
    
        public List<byte[]> allFlowers() throws IOException {
            return null;
        }
    
                    }

    Alternatively, instead of using the Business Method dialog you can manually add code to the bean class and to the remote interface class. However, if you use the Business Method dialog, the IDE adds code to both the bean class and the remote interface class, simultaneously.

  8. Fix imports in the bean and remote interface classes. In each class, place the cursor anywhere in the code, right-click to open the context menu, and select Fix Imports. A dialog box opens showing all necessary imports. Press OK and NetBeans generates the import statements. Alternatively, press Ctrl-Shift-I in each class to open the import dialog box.

  9. You have now declared your methods in the remote interface and implemented stubs in the bean class.

    The Projects window should now show two new nodes in the Enterprise Beans node, for your new methods, as shown here:
    Result

  10. Fill out the bean class with the following code, for exposing a single image and for exposing all images:
    @Stateless
    public class FlowerBean implements FlowerRemote {
    
        private static final String[] FLOWERS = {"aster", "honeysuckle", "rose", "sunflower"};
    
        public byte[] getFlower(String name) throws IOException {
            URL resource = this.getClass().getResource("/flower/album/resources/"+name+".jpg");
            return getBytes(resource);
        }
    
        public List<byte[]> allFlowers() throws IOException {
            List<byte[]> flowers = new ArrayList<byte[]>();
            for (String flower:FLOWERS) {
                URL resource = this.getClass().getResource("/flower/album/resources/"+flower+".jpg");
                flowers.add(getBytes(resource));
            }
            return flowers;
        }
    
        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();
        }
    
                }
  11. Create a new subpackage called resources. Copy the images found at the start of this tutorial into that package, as shown here:
    Result

    In your code, notice that the methods getFlower and allFlowers both make use of the images in this package.

You EJB module is now complete! In the next section, we will create a web service that will delegate to the EJB module, in order to retrieve the images at the appropriate points in the code.

Creating the Web Service

The goal of this section is to create a web application that contains a web service. The web service should delegate to the EJB module for the retrieval of images. Therefore, we will need to put the EJB module on the web application's classpath.

  1. Choose File > New Project (Ctrl-Shift-N). The New Project wizard appears. Select Web Application from the Web category. Click Next. The New Web Application wizard appears. Type FlowerService in Project Name, as shown below:
    Result

    Click Finish. The IDE creates a new web application project.

  2. To be able to access our EJB module from the web service that we will create later, we will need to put the former on the latter's classpath. First, right-click the web application's Libraries node and choose Add Project, as shown below:
    Result

    Next, browse to the EJB module and select it. You should now see a new node, for the EJB module, added to the web application's Libraries node, as below: Result

  3. Right-click the FlowerService node and choose New > Web Service. Alternatively, choose New > Other and then select Web Service under Web Services in the New File wizard, as below:
    Result
  4. In the New Web Service wizard, type FlowerService in Web Service Name and flower.album in Package Name. Select Create Web Service from Existing Session Bean and then browse to the EJB module and select it, as below:
    Result

    Click OK in the Browse Enterprise Bean dialog.

  5. Click Finish in the New Web Service wizard. The IDE adds the infrastructure of a web service to your application, which includes stubs for the methods obtained from the EJB module, as shown here:
    Result
  6. Click the Design toggle button in the top left corner of the editor. The Web Service Visual Designer is shown, as below:
    Java application with consumed ws

    You can use the Web Service Visual Designer to see the structure of your web service in one glance. In addition, you can add functionality to your web service by clicking buttons such as Add Operation. By using the Quality of Service section, you can very easily enable advanced features, such as web service security.

  7. Click the Source toggle button to switch back to the Source view. Rewrite the class so that it looks as follows:
    @WebService(serviceName = "FlowerService")
    
    public class FlowerService {
    
        @EJB
        private FlowerRemote ejbRef;
    
        @WebMethod(operationName = "getFlower")
        public Image getFlower(String name) throws IOException {
            byte[] bytes = ejbRef.getFlower(name);
            return getImage(bytes, false);
        }
    
        @WebMethod(operationName = "getThumbnails")
        public List<Image> getThumbnails() throws IOException {
            List<byte[]> flowers = ejbRef.allFlowers();
            List<Image> flowerList = new ArrayList<Image>(flowers.size());
            for (byte[] flower : flowers) {
                flowerList.add(getImage(flower, true));
            }
            return flowerList;
        }
    
        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);
        }
    
            }

The web service is now complete, delegating to the EJB module, and exposing its images.

Testing the Web Service

When you deploy a web service to an application container, the IDE lets you test the web service to see if it functions as you expect. The Tester application, provided by GlassFish and the Sun Java System Application Server, is available from the IDE for this purpose.

Below, we begin with the creation of an enterprise application. When we add our EJB module and our web service to the enterprise application, we will be able to deploy them together, as one unit, by deploying the enterprise application.

  1. Choose File > New Project (Ctrl-Shift-N). The New Project wizard appears. Select Enterprise Application from the Enterprise category, as below:
    Java application with consumed ws

    Click Next.

  2. In Project Name, type FlowerApplication. Make sure to deselect the Create EJB Module checkbox and the Create Web Application Module checkbox, because you do not want to create new modules. You should now see the following in the wizard: Java application with consumed ws

    Click Finish. A new enterprise application is added to the IDE. Now we need to add our two modules to the application.

  3. Right-click the FlowerApplication Java EE Modules node and choose Add Java EE Module, as shown below:
    Java application with consumed ws
  4. Choose both modules, as shown below:
    Java application with consumed ws

    Click OK. You should now see that the two modules are added to the application, as shown below:
    Java application with consumed ws

  5. Right-click the FlowerApplication node, choose Properties and type /FlowerService?Tester in the Relative URL field, as shown here:
    Java application with consumed ws

    Click OK.

  6. Right-click the FlowerApplication node and choose Run. If the server is not running, the IDE will start it. Then it will deploy the application, containing our two modules, to the server. Next, because of the settings specified in the previous dialog, the browser will open and display the Tester application, shown below:
    Java application with consumed ws

    Once you see the Tester application, open the Services window in the IDE, expand the Servers node, and notice that the IDE added new nodes for the deployed application and its modules, as shown here:
    Java application with consumed ws

    You now know for sure that the application has been successfully deployed.

  7. Click WSDL File in the Tester application and notice that the browser now shows the WSDL file:
    Java application with consumed ws
  8. Above, the browser shows, among other things, the location of the schema. Put the URL to the schema in the browser and then you can see the schema file:
    Java application with consumed ws
  9. Type the name of one of the images, such as "rose" in the Tester application:
    Java application with consumed ws
  10. Click the getFlower button and the IDE shows you information about the invocation in the browser:
    Java application with consumed ws

When you look at the "Method Returned" above, notice that it is garbled. What we want to have returned is an image, not a series of symbols that do not make sense. However, since java.awt.Image is not a valid schema type, we need to manually tweak the schema file to return the type that we want to have returned. We will do this in the next section.

Tweaking the WSDL File and Schema File

In this section, we add the WSDL file and schema file to our application. Then we tweak them to interpret arrays of bytes as Images. We also need to adjust various parts of our application to correctly locate our schema and WSDL file. In the process, you will be introduced to various tools in the IDE that can help you at this stage.

  1. Expand the web application until you reach the wsdl node:
    Java application with consumed ws

    Note: Currently the node is empty. The WSDL file and schema are generated at deployment, because we have been using the defaults; therefore this node, which would normally house them, is empty. Now that we want to interpret arrays of bytes as Images, we need to provide our own WSDL file and schema. We will put them in this node.

  2. Right-click the wsdl node, choose New > Other and use the XML Schema template, shown below, to create a file called FlowerService.xsd.
    Java application with consumed ws
  3. Repeat the process, but this time use the WSDL Document template and create a file called FlowerService.wsdl.

    You should now see the following in the wsdl node:

    Java application with consumed ws
  4. Copy the content of the WSDL file in the browser to the template you created above. If you used the defaults when creating and deploying the web service, the WSDL file should be here:
    http://localhost:8080/FlowerService/FlowerService?WSDL

    Edit the WSDL file and insert the namespace declarations. These decarations are necessary for the WSDL to be valid. Replace the lines at the beginning of the file:

    <!--
     Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.2-hudson-182-RC1.
    -->
    
    <!--
     Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.2-hudson-182-RC1.
    -->
    
                    <definitions targetNamespace="http://album.flower/" name="FlowerService">

    with the following:

    <definitions xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
        xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
        xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
        targetNamespace="http://album.flower/"
        xmlns="http://schemas.xmlsoap.org/wsdl/"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        name="FlowerService"
                    xmlns:tns="http://album.flower/">
  5. Similarly, copy the schema file into your template file. The schema file is here, by default:

    http://localhost:8080/FlowerService/FlowerService?xsd=1

    Edit the schema file and insert the namespace declarations. These decarations are necessary for the schema file to be valid. Replace the lines at the beginning of the file:

    <!--
     Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.2-hudson-182-RC1.
    -->
    
                            <xs:schema version="1.0" targetNamespace="http://album.flower/">

    with the following:

    <xs:schema xmlns:tns="http://album.flower/"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                            version="1.0" targetNamespace="http://album.flower/">
  6. Next, we will change the WSDL file so that our local schema file is referenced instead of the one that is on-line. Open the WSDL file in the Design mode, as shown below.
    Java application with consumed ws

    Expand the Types node. Right-click the Referenced Schema node.Choose Add > Import. The Add Import dialog opens.
  7. As shown below, you can now browse to the schema file and select it:


    Java application with consumed ws

  8. Click OK.

  9. Delete the other schema reference, which refers to the online schema file, which we do not want to refer to anymore, and then you will see that you can access nodes from the schema file, indicating that you have now correctly referenced it:
    Java application with consumed ws
  10. We need to explicitly make the application server use our own version of the WSDL file, otherwise the application server will generate its own WSDL file, from our web service's annotations.
    @WebService(serviceName = "FlowerService",
            wsdlLocation = "WEB-INF/wsdl/FlowerService.wsdl")

    You should now see the following in the web service class:
    Java application with consumed ws

  11. Finally, the point of this whole section is to have a modified schema file that specifies the expected content type of the return element. To identify the return element in the schema file, open the schema file and look at the line below, as well as the code in line 39, both of which may be on different lines in your own application: Java application with consumed ws
  12. Keep all the existing elements, but add the following attributes to both:

    xmime:expectedContentTypes="image/jpeg" xmlns:xmime="http://www.w3.org/2005/05/xmlmime"

    You should now see the following in the same lines:
    Java application with consumed ws

  13. Now, when you redeploy the web service to the Tester application, and invoke one of the operations, you will see that an image is correctly returned: Java application with consumed ws

Now that the Tester application has confirmed that images are correctly being returned, we can create our Swing client to retrieve and display them.

Note: You can find correctly modified versions of the WSDL and Schema files in the downloaded sample project. Both files are in the folder web/WEB-INF/wsdl.

Creating the Swing Client

The goal of this exercise is to create a client for the web service you previously created and deployed, and then add a GUI interface to that client. The interface displays the images that the web service passes as binary data.

  1. Choose File > New Project (Ctrl-Shift-N). The New Project wizard appears. Select Java Application from the Java category. Click Next. The New Java Application wizard appears. Type FlowerClient in Project Name and click Finish. The IDE creates a new Java application project.
  2. Right-click the FlowerClient project node and choose New > Web Service Client. In the New Web Service Client wizard, click WSDL URL, paste in the URL to the WSDL file, and enter the package, as shown below:
    Result
  3. Click Finish. The IDE downloads the WSDL file, adds client stubs for interacting with the web service, and adds nodes to the Projects window in the Java application project, as shown below:
    Result
  4. Add a JFrame to the project and name it FlowerFrame.
  5. Design the FlowerFrame with the following Swing components (For a tutorial on Swing components, see Designing a Swing GUI in NetBeans IDE):

    • JPanel. variable name: gardenFlowersPanel
      • JButtonGroup. variable name: buttonGroup1
      • JRadioButton. variable name: asterRadiobutton, button group: buttonGroup1, selected: true, text: Aster
      • JRadioButton. variable name: honeysuckleRadiobutton, button group: buttonGroup1, text: Honeysuckle
      • JRadioButton. variable name: roseRadiobutton, button group: buttonGroup1, text: Rose
      • JRadioButton. variable name: sunflowerRadiobutton, button group: buttonGroup1, text: Sunflower
      • JScrollPane. variable name: mainScrollPane
        • JPanel. variable name: mainPanel
          • LayoutManager. BorderLayout
          • JButton. variable name: mainPictureButton, text: Waiting for picture...
      • JLabel. variable name: titleLabel, text: Garden Flowers
      • JScrollPane. variable name: thumbnailScrollPane
        • JPanel. variable name: thumbnailPanel
          • LayoutManager. GridLayout
          • JButton. variable name: asterButton, preferred size: [160, 160], text: Waiting...
          • JButton. variable name: honeysuckleButton, preferred size: [160, 160], text: Waiting...
          • JButton. variable name: roseButton, preferred size: [160, 160], text: Waiting...
          • JButton. variable name: sunflowerButton, preferred size: [160, 160], text: Waiting...

    At this point, the FlowerFrame should look as follows:
    Result

  6. In the Source Editor, initialize the FlowerFrame like this:
    public static final String[] FLOWERS = {"aster", "honeysuckle", "rose", "sunflower"};
    private Map<String, Image> flowers;
    
    public FlowerFrame(Map<String, Image> flowers) {
    
        this.flowers = flowers;
        for (String flower:FLOWERS) {
            flowers.put(flower,null);
        }
    
        initComponents();
    
        setTitle("Garden Flowers [waiting for picture]");
    
        ItemListener rbListener = new RBListener();
        asterRadiobutton.addItemListener(rbListener);
        honeysuckleRadiobutton.addItemListener(rbListener);
        roseRadiobutton.addItemListener(rbListener);
        sunflowerRadiobutton.addItemListener(rbListener);
    
        ActionListener bListener = new ButtonListener();
        asterButton.addActionListener(bListener);
        honeysuckleButton.addActionListener(bListener);
        roseButton.addActionListener(bListener);
        sunflowerButton.addActionListener(bListener);
    
            } 
  7. When a JRadioButton is clicked, we want to show a new image in the main button:
    private class RBListener implements ItemListener {
    
        public void itemStateChanged(ItemEvent e) {
            showFlower();
        }
    
    }
    
    void showFlower() {
        Image img = null;
        if (asterRadiobutton.isSelected()) {
            img = flowers.get("aster");
            if (img != null) {
                mainPictureButton.setIcon(new ImageIcon(img));
                setTitle("Garden Flowers [Aster]");
            }
        } else if (honeysuckleRadiobutton.isSelected()) {
            img = flowers.get("honeysuckle");
            if (img != null) {
                mainPictureButton.setIcon(new ImageIcon(img));
                setTitle("Garden Flowers [Honeysuckle]");
            }
    
        } else if (roseRadiobutton.isSelected()) {
            img = flowers.get("rose");
            if (img != null) {
                mainPictureButton.setIcon(new ImageIcon(img));
                setTitle("Garden Flowers [Rose]");
            }
        } else if (sunflowerRadiobutton.isSelected()) {
            img = flowers.get("sunflower");
            if (img != null) {
                mainPictureButton.setIcon(new ImageIcon(img));
                setTitle("Garden Flowers [Sunflower]");
            }
        }
        if (img == null) {
            mainPictureButton.setIcon(null);
            setTitle("Garden Flowers [waiting for picture]");
        } else mainPictureButton.setText("");
            }
  8. When a JButton is clicked, we select the related JRadioButton:
    private class ButtonListener implements ActionListener {
    
        public void actionPerformed(ActionEvent e) {
            if (e.getSource() == asterButton) asterRadiobutton.setSelected(true);
            else if (e.getSource() == honeysuckleButton) honeysuckleRadiobutton.setSelected(true);
            else if (e.getSource() == roseButton) roseRadiobutton.setSelected(true);
            else if (e.getSource() == sunflowerButton) sunflowerRadiobutton.setSelected(true);
        }
            }
  9. In the Main class, the setThumbnails method will be called, which is in the FlowerFrame:
    void setThumbnails(Map<String, Image> thumbs) {
        Image img = thumbs.get("aster");
        if (img != null) {
            asterButton.setIcon(new ImageIcon(img));
            asterButton.setText("");
        }
        img = thumbs.get("honeysuckle");
        if (img != null) {
            honeysuckleButton.setIcon(new ImageIcon(img));
            honeysuckleButton.setText("");
        }
        img = thumbs.get("rose");
        if (img != null) {
            roseButton.setIcon(new ImageIcon(img));
            roseButton.setText("");
        }
        img = thumbs.get("sunflower");
        if (img != null) {
            sunflowerButton.setIcon(new ImageIcon(img));
            sunflowerButton.setText("");
        }
            }
  10. Fill out the Main.java class as follows:
    public class Main {
    
         private static int downloadedPictures;
    
         public static void main(String[] args) {
    
            final Map<String,Image> flowers = new HashMap<String,Image>(4);
            final Map<String,Image> thumbs = new HashMap<String,Image>(4);
    
            // Show the FlowerFrame:
            final FlowerFrame frame = new FlowerFrame(flowers);
            frame.setVisible(true);
    
            // The client connects to the service with this code:
            flowerclient.FlowerService_Service service = new flowerclient.FlowerService_Service();
            final flowerclient.FlowerService port = service.getFlowerServicePort();
    
            Runnable[] tasks = new Runnable[4];
    
            // The web service getFlower operation
            // is called 4 times, each in a separate thread.
            // When the operation finishes the picture is shown in
            // a specific button.
            for (int i=0; i<4;i++) {
                final int index = i;
                tasks[i] = new Runnable() {
                    public void run() {
                        try {
    
                            // Call the getFlower operation
                            // on the web service:
                            Image img = port.getFlower(FlowerFrame.FLOWERS[index]);
                            System.out.println("picture downloaded: "+FlowerFrame.FLOWERS[index]);
    
                            // Add strings to the hashmap:
                            flowers.put(FlowerFrame.FLOWERS[index],img);
    
                            // Call the showFlower operation
                            // on the FlowerFrame:
                            frame.showFlower();
    
                        } catch (IOException_Exception ex) {
                            ex.printStackTrace();
                        }
                        downloadedPictures++;
                    }
                };
                new Thread(tasks[i]).start();
            }
            // The web service getThumbnails operation is called
            // in a separate thread, just after the previous four threads finish.
            // When the images are downloaded, the thumbnails are shown at
            // the bottom of the frame.
            Runnable thumbsTask = new Runnable() {
                public void run() {
                    try {
                        while (downloadedPictures < 4) {
                            try {Thread.sleep(100);} catch (InterruptedException ex) {}
                        }
    
                        // Call the getThumbnails operation
                        // on the web service:
                        List<Image> images = port.getThumbnails();
                        System.out.println("thumbs downloaded");
    
                        if (images != null && images.size() == 4) {
                            for (int i=0;i<4;i++) {
                                thumbs.put(FlowerFrame.FLOWERS[i],images.get(i));
                            }
                            frame.setThumbnails(thumbs);
                        }
                    } catch (IOException_Exception ex) {
                        ex.printStackTrace();
                    }
                }
            };
            new Thread(thumbsTask).start();
        }
    
            }
  11. Remove the existing main method in the FlowerFrame class.

The web service is now complete, with code that interacts with the web service that delegates to the EJB module to exposes its images. Right-click the client and chose Run. The Swing application should start up and, after a moment, is filled with the images received from the web service.

Logging and Optimizing the Web Service

JAX-WS provides an easy and effective way to optimize binary data transfer. It is known as "message optimization", provided by the Message Transmission Optimization Mechanism (MTOM). Message optimization is the process of transmitting web service messages in the most efficient manner. It is achieved in web service communication by encoding messages prior to transmission and then de-encoding them when they reach their final destination. MTOM uses XOP (XML-binary Optimized Packaging) to transmit binary data to and from the web service. Enabling MTOM is simply achieved via the Web Service Designer, as shown in this section and described here.

To be able to verify, later, that MTOM is working correctly, we will begin by setting up a logging mechanism on the server. We can monitor the request and response messages without changing the client code. We will pass the system property -Dcom.sun.xml.ws.transport.http.HttpAdapter.dump=true to the server. This way, we will be able to monitor the SOAP messages, as well as the HTTP headers, that the web service is receiving and sending from and to the client.

  1. Open the Admin Console, from the server's node in the Services window, as shown here:
    Java application with consumed ws

    The Admin Console opens in the browser. Enter your username and password and press Enter.

  2. In the Admin Console, use the JVM Options section, shown below, to set this property on the server:
    -Dcom.sun.xml.ws.transport.http.HttpAdapter.dump=true
    Java application with consumed ws
  3. In the Services window, restart the server.
  4. While the server starts up, look in the Output window and make sure you see the property amongst the other server output, as shown below:
    Java application with consumed ws
  5. Redeploy the enterprise application to the Tester application, invoke an operation via the Tester application, and notice the Output window again, showing HTTP requests and responses, because of the logging mechanism that you enabled in the previous steps:
    Java application with consumed ws

    Now that we have HTTP logging working correctly, we will optimize the message transfer of our images.

  6. Open the web service in the Web Service Visual Designer and select "Optimize Transfer of Binary Data (MTOM)":
    Java application with consumed ws
  7. In the Services window, restart the server.
  8. While the server starts up, notice the following in the Output window:
    Java application with consumed ws

    As indicated in the highlighted lines in the Output window, by using MTOM we ensure that binary data is not contained within the SOAP body. Instead, it is sent as a SOAP attachment, while the attachment is included in the SOAP message.



See Also

For more information about using NetBeans IDE 6.0 to develop Java EE applications, see the following resources:

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

Bookmark this page

del.icio.us furl simpy slashdot technorati digg
Companion
Projects:
MySQL Database Server   Open JDK: an Open SourceJDK   GlassFish Community: an Open Source Application Server    Mobile & Embedded Community    Open Solaris   java.net - The Source for Java Technology Collaboration   Virtual Box - full virtualizer  Open ESB - The Open Enterprise Service Bus Powered by