Chapter 18. HTTP Support

In Chapter 7, “Client/Server Interaction,” we saw how to set up a simple client/server system using the OSGi HttpService. In Chapter 12, “Dynamic Configuration,” Toast used the HttpService to present a simple web UI for configuring the client’s tracking frequency. In this chapter we take a deeper look at this service and how to make the most of its capabilities.

The HttpService has been part of the OSGi specification since its inception. It allows applications to register servlets and resources to be served in response to HTTP requests. Since OSGi has always been about network-aware gateway devices, support for HTTP makes sense. In the broader enterprise and distributed application context, HTTP has proved to be a good choice of network protocol since it is lightweight, simple, and stateless.

In this chapter we assume a rudimentary understanding of Java servlets and HTTP and focus on the details of the HttpService. By the end of the chapter you will know about

• The HttpService API

• Registering and unregistering servlets and resources programmatically and declaratively

• Launching and testing HTTP content

• Using HTTP contexts to add security and Java Authentication and Authorization Service (JAAS) integration

• Using the Jetty-based HttpService implementation

18.1 The HttpService

HTTP has become a staple of system design, from web browsing to web services and RESTful interactions—it can be hard to find an application that does not involve HTTP in some way. Applications that act as clients can use the built-in JRE socket and URL support or something like the Apache HttpClient. Systems that need to handle HTTP requests, however, need more support.

Traditionally this support has come in the shape of either embedding an HTTP server such as Jetty in the application or running the application as part of an application server such as Tomcat, Jetty, or WebSphere. These approaches make assumptions about lifecycle and class loading that conflict with the OSGi model—they are not inherently modular.

The OSGi HttpService, however, was designed explicitly to tie into the OSGi modularity story and allow developers to compose server functionality by installing bundles just as they would in a client system. Using the HttpService, developers are insulated from the infrastructure used to service requests and can focus on their domain logic. Chapter 19, “Server Side,” talks more about this. Here we show how to use the service to define and manage HTTP-based content.

18.1.1 Concepts

There are three main concepts at play in the HttpService:

Content—The bytes to be served in response to requests. These can be statically or dynamically determined. Static content, resources, is just files or other data that is served blindly. Dynamic content is implemented using traditional servlet structures.

Location—HTTP-based content is accessed via URLs. When registering some content, developers must specify the location of that content in URL space, the so-called alias.

Context—All requests are processed in a context. The context defines how the request is processed—for example, the mapping from URL to local resource location or security and authentication requirements.

The HttpService surfaces control of each concept by allowing content to be registered at a particular alias in a defined context. The service itself has a simple API, as shown in the following snippet:

image

createDefaultHttpContextThis method creates and returns a default context for processing HTTP requests. This is needed only when implementing your own HttpContext. See Section 18.5, “HTTP Contexts and JAAS Integration,” for more detail.

registerResourcesThis method is used to register static content from a bundle under a unique alias.

registerServletThis method is used to register an instance of Servlet with the HttpService under a unique alias.

unregisterThis method unregisters the previously registered servlet or resource from the given alias.

18.2 Registering and Unregistering a Servlet

As an example of using the HttpService, we’re going to look back at Toast’s org.equinoxosgi.toast.client.tracking.config bundle from Chapter 12, “Dynamic Configuration.” The DS component for this bundle references the HttpService as follows:

image

As this is an immediate component, DS will instantiate and activate it as soon as its configuration is satisfied. The Component class is shown here:

image

The startup method creates an instance of TrackingConfigServlet and uses the HttpService’s registerServlet method to register the servlet under the alias /client/tracking-config. The registerServlet method takes the following parameters:

aliasThe location in URL space at which the servlet lives

servletThe servlet object to register

initparamsInitialization arguments for the servlet, or null if there are none; this argument is used by the servlet’s ServletConfig object

contextThe HttpContext object for the registered servlet, or null if a default HttpContext is to be created and used

The startup method also calls the HttpService’s registerResources method to register the path /resources/images as the place in the bundle to look to fulfill resources requested from the URI /client/tracking-config/images (see Figure 18-1). The method registerResources takes three parameters:

aliasThe location in URL space at which the resources reside

nameThe bundle-relative location of the resources that are being registered

contextThe HttpContext object for the registered resources, or null if a default HttpContext is to be created and used

Figure 18-1 The registered bundle resources

image

The alias parameter is the resource’s logical location, whereas the name parameter is the resource’s physical location in the bundle. Separating the resource’s logical location from its physical location allows the resources to be reorganized inside the bundle without affecting the URLs used by clients to access them.

When the Toast Client is launched and a web browser is pointed at http://localhost:8081/client/tracking-config, the page shown in Figure 18-2 is displayed.

Figure 18-2 Toast’s tracking config servlet, with image resources

image

18.3 Declarative HTTP Content Registrations

So far we’ve discussed how to register a servlet and resources programmatically via the API provided by the HttpService. In our examples the servlet and resources are registered and unregistered by a DS component as it is activated and deactivated. It is also possible to register servlets and resources via the Extension Registry, as seen in Chapter 16, “Extensions.”

The org.eclipse.equinox.http.registry bundle defines the following extension points:

org.eclipse.equinox.http.registry.servletsUsed to register a servlet, defined by the specified Java class, at the given alias

org.eclipse.equinox.http.registry.resourcesUsed to register a resource, identified by the given path within the bundle, at the given alias

Using extensions has the benefit that registering the servlet and the resources requires no class loading and no object creation. Even the creation of the servlet is delayed until the HttpService receives the first HTTP request for the servlet. Now that the registrations are performed declaratively, it is no longer necessary to have a DS component class. This results in fewer dependencies on other bundles and faster loading.

To use the Equinox Extension Registry for contributing to the HttpService from within Equinox, the following bundles should be added to your product or launch configuration:

image

18.4 Using Jetty

Equinox supplies a simple HTTP service implementation in the bundle org.eclipse.equinox.http. This is a compact and lightweight implementation of the OSGi standard based on the Servlet 2.1 specification. For much of Toast this is sufficient. However, if your requirements go beyond the 2.1 standard—using more modern servlets, JSPs, tag libs, and so on—you need a different HTTP service. Fortunately, the Equinox project also supplies an HTTP service implementation based on Jetty.

Jetty is a highly embeddable, high-performance, open-source servlet engine used by hundreds of thousands of web sites on the internet and countless more internal and embedded systems. The project’s focus on integration with the surrounding system makes Jetty an ideal candidate for use in OSGi systems.

The version of Jetty that comes with the Equinox SDK is available as a set of OSGi bundles—simply drop these into an OSGi system and use the Jetty API. The Equinox project provides an implementation of the OSGi HttpService based on Jetty in the org.eclipse.equinox.http.jetty bundle. This bundle is included in the Equinox SDK that you have been using in your target platform. The Jetty-based HttpService has been enhanced to support running both static and dynamic JavaServer Pages (JSPs) using Jetty’s built-in support.

To add Jetty as the basis for the client’s HTTP requirements, open the client.product and replace the old HTTP bundle, org.eclipse.equinox.http, with the following Jetty bundles:

image

Now the configuration management web UI can be updated to make use of JSPs, tag libs, and AJAX frameworks such as Dojo. For even more advanced UIs, you can use the Eclipse Rich Ajax Platform (RAP) technology to get RCP-like function in the browser from one code base.

18.5 HTTP Contexts and JAAS Integration

It is quite common in various HTTP scenarios to require users to log in. Fortunately, Equinox includes support of standard JAAS integration. This functionality is found in the org.eclipse.equinox.security.* bundles in the Equinox SDK. In this section we combine JAAS support with the HttpService’s HttpContext facilities to add HTTP basic authentication to protect the configuration of the Toast Client.

18.5.1 Basic HTTP Authentication and Login

HTTP manages security through the HTTP context used when processing servlet and resource requests. This context is supplied when registering a servlet with the HTTP service. Until now we have just been passing null for the context argument—letting the HttpService use its default context. Here we update the Toast Client’s configuration management servlet from Chapter 12, “Dynamic Configuration,” to require logins.

To add security, we need to supply our own context to ensure that the user is logged in for every request. In particular, we need an implementation of HttpContext.handleSecurity. The following code snippet sketches an implementation of this method for the HTTP Basic authentication method. For the full code, look at SecureBasicHttpContext in the org.equinoxosgi.toast.core.security bundle from the sample code.

image

The method first confirms that the request is using the Basic authentication method. It then decodes the authentication information—user name and password—and attempts a login using these credentials. If the login is successful, the request is configured with the authorization information.

The login code hooks into the JAAS infrastructure, as shown in the following snippet. Here the code first checks to see if there is already a session associated with the request and if that session has already been authenticated. If so, there is nothing more to do. If not, we need to create and configure a login context.

image

The login context is used to tell JAAS how and where to get passwords as well as how to validate the credentials. The how and where are defined in the configFile argument to createContext. This file is supplied by the system driving the security policy—in our case the client itself. In more sophisticated systems the configuration would be done in a more centrally managed place. The following text shows the simple configuration file used here:

image

The jaas_config.txt file defines a SimpleConfig element that consists of a class that implements the JAAS LoginModule interface and a set of properties. This login module uses the Equinox Extension Registry to discover further login module implementations to which it delegates. In particular, here we are using the simpleLogin extension supplied by the Toast security bundle.

The simpleLogin extension identified in the configuration file ultimately points to the SimpleLoginModule code shown here:

image

When login is called by the system, it requests the needed information by posting a set of callbacks. The login context we saw before handles the callbacks by filling in the user name and password from the basic authentication credentials of the current request. Our login module then checks the supplied values to see if they are valid. In this simple case we just have a hard-coded “user” with a “password.” Clearly other login modules would do more sophisticated validation by consulting the operating system or enterprise directory servers.

18.5.2 Running the Secured Client

It is time to update the client to hook in the new authentication support. Setting up security in the client is easy—just update the place where the configuration management web UI content, the servlet and resources, is registered; that is, update the Component class’s startup method as shown in this snippet:

image

The essential change is to instantiate the SecureBasicHttpContext discussed previously and use it in all HttpService register* calls. The context is created using the root of the resource content in the bundle and the example configuration file, jaas_config.txt. At this point it is worthwhile to make sure that the jaas_config.txt file is in the tracking configuration bundle and that the bundle’s build.properties file includes it in the list of binary build resources, as discussed in Chapter 9, “Packaging.”

Now open client.product and add the bundles required for security:

org.eclipse.equinox.security
org.equinoxosgi.toast.backend.security

Save everything and run the client product. When you go to the tracking configuration page at http://localhost:8081/client/tracking-config, you should first be prompted to log in to the Toast Client Management realm, as shown in Figure 18-3. Supply “user” and “password” as the credentials to configure the client’s tracking behavior as before.

Figure 18-3 Client tracking configuration login dialog

image

18.6 Troubleshooting

This section discusses some problems that are commonly encountered while working with the HttpService.

18.6.1 BindException

During the course of development it is common to see the following exception when launching the OSGi framework:

image

This exception means that the HttpService was unable to bind to the port on which it was told to listen because the port is already being used by another application. The most common cause of this is another running JVM that you forgot to terminate. The Eclipse Console view can be used to find and terminate previously launched JVM instances.

In cases where the cause is not another JVM, you’ll need to rely on some detective work to find which process is using the port. A useful command-line utility that works on Windows, Macintosh, and Linux is netstat, which displays the ports that are in use and by which processes. For example, try the following command:

image

18.6.2 On Which Port Is the HttpService Listening?

Sometimes it is helpful find out on which port the HttpService is listening. The easiest way is to launch the OSGi framework with the -console command-line option and use the Equinox console to query the properties of the org.eclipse.equinox.http bundle. Use the bundle command to display the details of the org.eclipse.equinox.http bundle:

image

The output shows that the HttpService is listening on port 80.

HttpService Properties Are Not Defined by the OSGi Specification

While querying the registered service in this way works for the default Equinox implementation of the HttpService as defined by the bundle org.eclipse.equinox.http, the OSGi specification does not define properties such as http.port, http.address, http.schema, and http.timeout. Other implementations of the HttpService may or may not register such properties. Note that it is not always possible for the HttpService implementation to know the ports on which the application server is listening. For more information, see the following OSGi bug report: https://www.osgi.org/members/bugzilla/show_bug.cgi?id=502.

18.7 Summary

HTTP is a well-known interaction model and protocol. The OSGi HttpService is a simple and straightforward approach to exposing HTTP in OSGi. It allows system developers to create web applications by composing bundles that contribute servlets, resources, JSPs, and more, bringing the power of OSGi modularity to the web world.

In this chapter we discussed the HttpService interface and how to register servlets and resources both programmatically from a DS component and declaratively using extension points.

We also enhanced the Toast Client configuration management facility to have JAAS integration for login handling. The login support developed is completely generic and can be used in a number of different scenarios. Through the Equinox infrastructure it is also possible to register a number of different login modules, from simple example modules to comprehensive enterprise authentication systems.

Whether it is the basic Equinox implementation or the more comprehensive Jetty-based version, the HttpService is a versatile addition to many OSGi-based systems.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.188.151.107