Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

Create a Java applet to download information in remote Web services

Submit, receive, and analyze XML Web services messages through your browser

Nicholas Chase (nicholas@nicholaschase.com), Open Source Developer and Analyst, Studio B
Nicholas Chase, a Studio B author, has been involved in Web site development for companies such as Lucent Technologies, Sun Microsystems, Oracle, and the Tampa Bay Buccaneers. Nick has been a high school physics teacher, a low-level radioactive waste facility manager, an online science fiction magazine editor, a multimedia engineer, and an Oracle instructor. More recently, he was the Chief Technology Officer of an interactive communications firm in Clearwater, Florida, USA, and is the author of several books on XML and on Web development, including XML Primer Plus (Sams). He's currently trying to buy a farm so that he and his wife can raise alpacas and mutant chickens. He loves to hear from readers and can be reached at nicholas@nicholaschase.com.

Summary:  Start with a Java™ applet and build a server-based proxy system that uses your browser to access an arbitrary Web service. You'll use JavaScript code to access applet-based information and call a servlet, which retrieves the remote information. Thus, you bypass the same-server restrictions on what an applet can and cannot do.

Date:  04 Sep 2008 (Published 14 Oct 2004)
Level:  Intermediate PDF:  A4 and Letter (135 KB)Get Adobe® Reader®

Activity:  40331 views
Comments:  

Applets have always been designed to play in a 'sandbox' in which they can't hurt anything on a user's system, so their security is tighter than that of their server-based application counterparts. For example, a Java application can easily make a network connection to another server to request a Web service response; an applet can, too -- as long as it's talking only to the server on which it was originally hosted. But what if you want an applet that can make arbitrary Web requests?

In this article, I show you how to create a system that uses your browser to request and interact with Web service data from an arbitrary source. First, I create the basic Java applet, then I create the JavaScript code that pulls the data into the Web page. Finally, I create a servlet that acts as a proxy for non-local requests.

This article assumes that you are familiar with Java technology and (to a lesser extent) with XML. In addition to a Java development environment such as J2SE 1.4 or above, you'll need several pieces of software for this article. To send and receive the SOAP messages, you'll need the SOAP with Attachments Application Program Interface (API) for Java, or SAAJ (see "Send and receive SOAP messages with SAAJ" for help in setting it up) and you'll need a servlet engine such as IBM® WebSphere® Application Server or Apache Tomcat to run the servlet. See Resources for links to the various software packages you'll need.

A simple request

First, take a look at the request you're ultimately going to make from the applet. Although this technique works for any kind of data you can pass through a URL, this article focuses on Web services, so I'll start with the simple SOAP message in Listing 1.


Listing 1. A simple SOAP message
<SOAP-ENV:Envelope 
               SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:ns1="urn:chaosmagnet-quote"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
  <SOAP-ENV:Body>
      <ns1:getQuoteResponse>
         <return xsi:type="xsd:string">The early bird gets the worm, but it's the 
second mouse that gets the cheese...</return>
      </ns1:getQuoteResponse>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

To make things simple, I made this message available through a simple GET request at http://www.nicholaschase.com/testsoap.php. Making it available at a URL allows you to create a simple Java application (Listing 2) to retrieve and parse it.


Listing 2. Access a URL through a Java application
import java.net.URLConnection;
import java.net.URL;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;

public class SendRequest {

  public static void main(String args[]){

     try{

        URL url = new URL("http://www.nicholaschase.com/testsoap.php");
        URLConnection urlconn = url.openConnection();

        Document doc = null;
        try {
           DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
           DocumentBuilder db = dbf.newDocumentBuilder();
           doc = db.parse(urlconn.getInputStream());

           System.out.println(doc.getDocumentElement()
                .getFirstChild().getNextSibling()
                .getFirstChild().getNextSibling()
                .getFirstChild().getNextSibling().getFirstChild().getNodeValue());

        } catch (IOException e) {
           System.out.println("can't find the file:"+e.getMessage());
        } catch (Exception e) {
           System.out.print("Problem parsing the XML.");
        }
     } catch (Exception e){
        e.printStackTrace();
     }

  }
}

Signed versus unsigned applets

Normally, applets are only allowed to establish connections with a limited number of servers. To bypass this restriction, you need to digitally sign your applets. Doing so removes the restriction, but causes the browser to display an alert box that asks if the user wants to accept the signature. If you feel that your audience may be scared off by such an alert, you're better off working around the restrictions, as I show you here.

First, create the actual URLConnection. From there, you can feed its InputStream to the DocumentBuilder as the source from which to build the Document object. I realize the output statement is a bit awkward, but because this article is about accessing the data rather than analyzing it, I'm just working my way down to the actual quotation.

Compile and run the application from the command line, and you should get the expected response:

The early bird gets the worm, but it's the second mouse that gets the cheese...

You might be wondering why I went to the trouble of dealing with the XML directly rather than using, say, the SAAJ. The answer is that ultimately I'll package this code as an applet that runs on computers over which I have no control, so I want to stay with classes that are part of the Java technology itself.


Create the applet

The applet itself is simple, as Listing 3 shows.


Listing 3. A simple applet
import java.applet.*;
import java.awt.*;

public class SendRequest extends Applet {

  public void paint(Graphics g) {
      g.drawRect(0, 0, 499, 149);
      g.drawString("Printing...", 5, 70);
  }

}

This applet simply draws a rectangle and displays the word "Printing..." inside it each time the applet is displayed. Save the class and compile it, then open a second text file to create the HTML page that displays the applet, as shown in Listing 4.


Listing 4. The HTML page displaying the applet
<HTML>
<HEAD>
   <TITLE>A Simple Program</TITLE>
</HEAD>
<BODY>
   <CENTER>
      <APPLET CODE="SendRequest.class" WIDTH="500" HEIGHT="150">
      </APPLET>
   </CENTER>
</BODY>
</HTML>

Notice that this typical HTML page includes an APPLET tag that calls the applet code. Save this HTML page in the same directory as the SendRequest.class file, then open it in your browser. You should see a result similar to Figure 1.


Figure 1. The simple applet
Figure 1. The simple applet

Now, add the code to retrieve the URL.


Access the response from the applet

Adding the URL retrieval to the applet is straightforward, as Listing 5 shows.


Listing 5. Add the URL retrieval to the applet
import java.applet.*;
import java.awt.*;

import java.net.URLConnection;
import java.net.URL;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;

public class SendRequest extends Applet {

  public void paint(Graphics g) {
     g.drawRect(0, 0, 499, 149);
     g.drawString(getResponseText(), 5, 70);
  }

  public String getResponseText(){

    try{

      URL url = new URL("http://www.nicholaschase.com/testsoap.php");
      URLConnection urlconn = url.openConnection();

      Document doc = null;
      try {
       DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
       DocumentBuilder db = dbf.newDocumentBuilder();
       doc = db.parse(urlconn.getInputStream());
       return (doc.getDocumentElement()
            .getFirstChild().getNextSibling()
            .getFirstChild().getNextSibling()
            .getFirstChild().getNextSibling()
               .getFirstChild().getNodeValue());
      } catch (Exception e) {
       return "Can't get the string.";
      }
    } catch (Exception e){
      return "Problem accessing the response text.";
    }

  }
}

Here, I include the code wholesale from the original application, but I've changed the main() method to the getResponseText() method, which I then print to the page when the browser displays the applet.

Everything should work, but if you refresh the browser, you'll see that all is not as it seems -- see Figure 2. (To see the changes, you may have to hold down the Ctrl key while you refresh the page.)


Figure 2. Calling the applet from the local file system
Figure 2. Calling the applet from the local file system

So, what's the problem? As I mentioned earlier, applets are designed with certain security limitations, one of which is the inability to access a server other than the one from which the applet was originally downloaded. So, because I'm trying to call a URL on www.nicholaschase.com, I simply need to upload the applet and the HTML file to that server. Then, I can call the applet and everything will work as advertised, as you can see in Figure 3.


Figure 3. Accessing the applet from the proper server
Figure 3. Accessing the applet from the proper server

Now that I have the data, I can access it from within the HTML page.


Access applet data through JavaScript

The ultimate goal of this process is to be able to use JavaScript code to analyze the retrieved data. The key to the process is to treat the applet as an object -- in fact, the APPLET tag will eventually be replaced by the object tag. To replace the tag, you must assign it an id attribute, as shown in Listing 6:


Listing 6. Accessing the applet as an object
<HTML>
<HEAD>
   <TITLE>A Simple Program</TITLE>
</HEAD>
<BODY>
   <CENTER>
      <APPLET CODE="SendRequest.class" WIDTH="500" HEIGHT="150" id="TheApplet">
      </APPLET>
   </CENTER>

   <b>The returned data is:</b><br />

   <script type="text/javascript">
      document.write(TheApplet.getResponseText());
   </script>

</BODY>
</HTML>

Assigning the applet an id attribute enables you to treat the applet as a simple object, which in turn enables you to make a direct call to the applet's methods. If you save the page and refresh it, you can see that the information gets pulled into the page (Figure 4).


Figure 4: Accessing the applet data through JavaScript
Figure 4:  Accessing the applet data through JavaScript

Now all that's left is to access an arbitrary URL.


Create the proxy

Everything is now working, but because of security requirements, you can access only the server from which you downloaded the applet. What happens if you want to access a different server?

Version differences

If you've using another version of SAAJ, such as the Axis 1.2 beta SAAJ library, you may need to use addBodyElement instead of addChildElement.

For example, suppose you wanted to pull this quote live from the Quote of the Day service. Because the applet can connect only to its own server, you can't connect to the applet directly. But the server can connect to anything, which means that instead of connecting to the data directly, you can connect to a servlet that retrieves the data.

The code in Listing 7 creates a servlet that retrieves a response from the Quote of the Day service.


Listing 7. Servlet to retrieve the remote information
import javax.servlet.http.*;
import javax.servlet.*;
 
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPElement;


import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.Source;

import javax.xml.transform.stream.StreamResult;

public class SendingServlet extends HttpServlet {

    public void doGet(HttpServletRequest req, HttpServletResponse resp)
                                         throws ServletException {
    try {
     
       //First create the connection
       SOAPConnectionFactory soapConnFactory = 
                      SOAPConnectionFactory.newInstance();
       SOAPConnection connection = 
                        soapConnFactory.createConnection();
         
       //Next, create the actual message
       MessageFactory messageFactory = MessageFactory.newInstance();
       SOAPMessage message = messageFactory.createMessage();
         
       //Create objects for the message parts            
       SOAPPart soapPart =     message.getSOAPPart();
       SOAPEnvelope envelope = soapPart.getEnvelope();
       SOAPBody body =         envelope.getBody();

       //Populate the body
       //Create the main element and namespace
       SOAPElement bodyElement = 
           body.addChildElement(envelope.createName("getQuote" , 
                                     "ns1", 
                                     "urn:xmethods-qotd"));
       //Save the message
       message.saveChanges();

       //Send the message and get a reply   
            
       //Set the destination
       String destination = 
              "http://webservices.codingtheweb.com/bin/qotd";
       //Send the message
       SOAPMessage reply = connection.call(message, destination);

       //Check the output
       //Create the transformer
       TransformerFactory transformerFactory = 
                         TransformerFactory.newInstance();
       Transformer transformer = 
                       transformerFactory.newTransformer();
       //Extract the content of the reply
       Source sourceContent = reply.getSOAPPart().getContent();

       resp.setHeader("Content-Type", "text/plain");

       //Set the output for the transformation
       StreamResult result = new StreamResult(resp.getWriter());
       transformer.transform(sourceContent, result);

       //Close the connection            
       connection.close();
            
     } catch(Exception e) {
      System.out.println(e.getMessage());
     }

  }

}

This script looks long and complicated, but it's really straightforward. First, create the SOAPConnection and the message objects. Next, populate the objects with a single getQuote element, as required by the Quote of the Day service.

After you've finished creating the request message, send it to the service and retrieve the reply. The reply comes back as a SOAPMessage object, but you need to pass the actual text of the message to the servlet's Response object. To do so simply use an identity XSLT transformation with the response as the destination.

If you compile and install this servlet just as you would any other servlet -- see Resources for help -- you can call it directly from the browser to see the results (Figure 5).


Figure 5: The remote response, as retrieved by the local servlet
Figure 5: The remote response, as retrieved by the local servlet

From here, pulling the remote information into the applet is as simple as calling the servlet, as the code in Listing 8 shows:


Listing 8. Calling the remote data from the applet
...
  public void paint(Graphics g) {
      g.drawRect(0, 0, 499, 149);
      g.drawString(getResponseText(), 5, 70);
  }


  public String getResponseText(){

     try{

        URL url = new URL("http://localhost:8080/servlet/SendingServlet");
        URLConnection urlconn = url.openConnection();

        Document doc = null;
        try {
           DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
           DocumentBuilder db = dbf.newDocumentBuilder();
           doc = db.parse(urlconn.getInputStream());
  
           return (doc.getDocumentElement()
                   .getFirstChild().getFirstChild().getFirstChild()
                   .getFirstChild().getNodeValue()); 
        } catch (Exception e) {
           return "Can't get the string:"+e.toString();
        }
     } catch (Exception e){
        return "Problem accessing the response text."+e.toString();
     }

  }
}

Notice that the code is the same, with two exceptions. First, rather than calling the data directly, I'm calling the servlet that retrieves the data. Second, because the service returns a message without the extra line breaks, I've cleaned up the retrieval a bit.

To see the results, move the applet and the HTML page to the server on which you've installed the servlet. You can then access the applet and view the results (Figure 6).


Figure 6: Seeing the results
Figure 6: Seeing the results

Conclusion

In this article, I have explained how to create a system that uses your browser to access an arbitrary Web service. JavaScript code calls a method within an applet, which calls a servlet, which retrieves the remote information. In this way, you bypass restrictions on what an applet can and cannot do.

From here, you can take several routes to clean up the process or enhance its functionality. Because you're pulling the data into the JavaScript code, you no longer have to display the actual applet on the page. You can also modify the applet to retrieve more than one piece of information from the service or pass information back from a single request rather than making a new request every time the user changes windows.

If you want to go all out, you have the option of changing the servlet so that it takes parameters from the applet. Those parameters can determine what service the servlet calls or even parameters to pass to that service. Using methods (as I did here with getResponseText()), you can even write JavaScript code to pass those parameters in to the applet, allowing the user to decide what information is ultimately presented.


Resources

About the author

Nicholas Chase, a Studio B author, has been involved in Web site development for companies such as Lucent Technologies, Sun Microsystems, Oracle, and the Tampa Bay Buccaneers. Nick has been a high school physics teacher, a low-level radioactive waste facility manager, an online science fiction magazine editor, a multimedia engineer, and an Oracle instructor. More recently, he was the Chief Technology Officer of an interactive communications firm in Clearwater, Florida, USA, and is the author of several books on XML and on Web development, including XML Primer Plus (Sams). He's currently trying to buy a farm so that he and his wife can raise alpacas and mutant chickens. He loves to hear from readers and can be reached at nicholas@nicholaschase.com.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=XML, SOA and Web services, Java technology
ArticleID=18048
ArticleTitle=Create a Java applet to download information in remote Web services
publish-date=09042008
author1-email=nicholas@nicholaschase.com
author1-email-cc=dwxed@us.ibm.com

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

For articles in technology zones (such as Java technology, Linux, Open source, XML), Popular tags shows the top tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), Popular tags shows the top tags for just that product zone.

For articles in technology zones (such as Java technology, Linux, Open source, XML), My tags shows your tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), My tags shows your tags for just that product zone.

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Try IBM PureSystems. No charge.

Special offers