Chapter 13. Web Portal

So far the Toast Back End has been largely headless—content is written to the console, but there is no user interaction. In this chapter we add a web-based user interface to Toast. The goal here is not to create a fancy UI but rather to talk about some commonly used extensibility mechanisms and metaphors set in the context of providing a UI for Toast.

We use this context to introduce the Whiteboard Pattern, a powerful style of using OSGi services to aggregate operations. In building the portal we also look at how to insulate our domain code from OSGi in cases where explicit OSGi use is inevitable.

In this chapter we do the following

• Introduce and explore the Whiteboard Pattern

• Build on our current back end infrastructure and create an extensible servlet structure by composing request handlers

• Use the extensibility infrastructure to create a simple web UI portal for fleet management

• Demonstrate the use of higher-order cardinality and dynamicity in Declarative Services

• Implement a strategy for isolating domain code from OSGi infrastructure

13.1 Portal

Our modest Toast Back End has already demonstrated some of the value of OSGi on servers—we are able to reuse bundles on the client and server, and composing collections of servlets is straightforward. In the larger context, the benefits of OSGi seen on desktops are at play on servers. In this chapter we explore some of these and create a simple extensible web UI portal using techniques similar to those used in other scenarios.

In the Toast context we have a rich client UI. To create a similarly rich server UI would require significant effort and the use of technology such as the Eclipse Rich Ajax Platform (RAP). Here, we will create a simple portal that can be dynamically extended with new actions. For the most part we focus on the portal extensibility mechanisms and leave aside the details of web design and compelling workflows. Figure 13-1 shows a screen shot of the portal and the list of vehicles being managed.

Figure 13-1 Toast Back End portal

image

The Toast Back End manages a set of vehicles. A UI on the back end should allow users to browse and interact with the vehicles. Since we are using web browsers and HTTP, Java servlets are a convenient means of implementing this functionality. We could have each new piece of functionality implemented as an independent servlet, but this gets challenging to coordinate, not to mention that it makes it harder to demonstrate interesting OSGi capabilities. Instead, the Toast Portal uses one servlet, the PortalServlet, and the Whiteboard Pattern to enable extensibility.

The bulk of this chapter is a tour of the web portal code. As such, you should load the Chapter 13 sample from the Samples Manager to help in the exploration.

13.2 The PortalServlet

The PortalServlet acts as a request dispatcher. Incoming requests are inspected and matched with, and dispatched to, a suitable handler. It is a subclass of javax.servlet.http.HttpServlet, and the following snippet shows its doGet method—the only significant functionality in the class. The two most important lines are highlighted in the snippet.

image

The portal servlet accepts HTTP GET requests and uses the information supplied to determine an action to execute. To make the portal extensible, an action lookup mechanism is introduced. This isolates the servlet from the details of how actions are contributed. As we see in the first highlighted line, the portal servlet gets the relevant action from the action lookup mechanism. Once the action is found, handling of the request is delegated to the action. The portal is not involved in producing the response to any requests other than requests to the root of the servlet URL space or unrecognized requests.

As with the other cases in Toast, a DS component is needed to get the HttpService and register the required servlets. From an architectural point of view the portal is a configuration of the portal servlet and an action lookup mechanism. Together they define how actions are contributed, discovered, and executed.

The portal component combines the action lookup mechanism, business logic, and the control center to create a PortalServlet that is then registered with the HttpService. The key code for the Portal component is shown in the following snippet. In practice, center, lookup, and http are all fields containing services statically referenced by the portal component’s portal.xml.

image

13.3 Action Lookup Using Services

There are many possibilities for implementing the action lookup mechanism. All must implement the interface shown in the following IActionLookup snippet. Here getAction allows for the lookup of an action, and getAvailable and getActionProperty let clients interrogate the structure of the available actions.

image

In this chapter we will implement an OSGi service-based action lookup mechanism. In particular we introduce the Whiteboard Pattern as a means of discovering actions registered as services. The Whiteboard Pattern inverts the typical service orientation. In the registration approach used so far in the book, clients of, say, the HttpService discover the service and register their interests and capabilities. In the Whiteboard Pattern, the interested parties leverage the OSGi service registry by registering services, and the event sources discover them by querying the service registry. The registered services neither know nor care how they are used.

In keeping with our use of Declarative Services, we implement an IActionLookup that uses DS and the OSGi services following the Whiteboard Pattern. Using the whiteboard approach, action providers register their actions as services with the OSGi service registry. The action lookup mechanism then discovers all available action services and makes them available to the portal. Chapter 15 gives much more detail on the Whiteboard Pattern and dives deeply into the implementation detail of the portal.

So far we have used DS in one way—to discover single services to which our components are statically bound. For a whiteboard component we need to allow both multiple service object discovery and dynamic service contribution. The following snippet shows the markup for the service-based IActionLookup component that meets these needs:

image

The snippet declares that the component references 0 or more IPortalAction services. By allowing for 0 references, the component says the referenced service is optional—the portal can run without any actions. With the upper bound set to n, the component allows for many services to be bound to it.

As we are building a dynamic system, the IPortalAction service reference has its policy set to dynamic. This allows referenced services to come and go without affecting the activation state of the component—the service action lookup component, and thus the portal, keeps running even if the actions change.

As IPortalAction services come and go, addAction and removeAction maintain a catalog of the discovered services. To get a sense of how this works, take a look at the addAction snippet:

image

The first thing to notice is that the addAction method’s parameter is of type ServiceReference, whereas normally it has been the actual service type, for example, IPortalAction. One of the advantages of using DS is that it enables laziness—declared services are not instantiated until they are actually referenced. By using a ServiceReference, we tell the DS runtime to delay the instantiation of the service object even further until we programmatically dereference the ServiceReference object by calling the DS component’s ComponentContext.locateService(String, ServiceReference) method. If the service represented by the ServiceReference is never used, it is never instantiated. Since typically only a few portal actions are used, this saves time and space.

The second point of interest in this code is the PortalAction wrapper class. A PortalAction is an IPortalAction that wraps a ServiceReference discovered by DS. The PortalAction presents an opaque façade that lazily gets the real service when the action is to be executed. The following snippet illustrates the IPortalAction.execute method:

image

Notice that the ComponentContext is used to look up the cached ServiceReference. The execute request is then delegated to the real action implementation. Readers interested in more detail on these points should review the ServiceActionLookup and PortalServlet code and look at Section 15.2.6, “The Whiteboard Pattern.”

The final key element of the addAction method is the use of service properties. The first line of the method retrieves the action property from the service reference. When the service provider registered or declared the service, it supplied a value for this property. The portal uses the value as an identifier for the action. Incoming HTTP requests identify the action to run by including the related ID as a parameter in the HTTP request. The PortalServlet extracts the parameter and passes it to the IActionLookup. Refer back to the servlet code in Section 13.2, “The PortalServlet,” to see the control flow.

13.4 Declaring a Portal Action

Adding an action using the Whiteboard Pattern is as easy as registering an IPortalAction service with the OSGi service registry. This can be done using declarative or traditional service techniques. Since we’ve adopted DS, we declare a DS component for each portal action.

Action implementations need only implement the simple interface shown in the following snippet:

image

Shown next is the code for the browse action. This action presents a UI allowing users to browse aspects of a particular vehicle. This action simply generates a web page with all the browsing actions for a particular vehicle.

image

The browse service is contributed to the system using the following DS component declaration:

image

The key part of this markup is the two <property> elements—the action and the label. As we saw, the portal uses the action property value to identify actions. Similarly, the label property is used to affect the appearance of the action in the UI—the value of this property is presented to the user.

To add a bit more flexibility to action contributions, IActionLookup includes a simple action hierarchy model using paths in the action property. For example, the action property for the set of actions related to browsing a vehicle all start with browse/. The portal UI can then dynamically identify the browsing capabilities by looking only for the actions with that prefix.

Of course, actions can be contributed from any bundle. For example, the following snippet shows how the UI for tracking a vehicle is contributed by the org.equinoxosgi.toast.backend.tracking.ui bundle. Notice the path in the action property value.

image

13.5 Whiteboard Pros and Cons

This example portal is not intended to be comprehensive or even sophisticated. It serves two purposes: First, it gives the Toast Back End a UI; and second, it motivates a discussion around the Whiteboard Pattern and domain code isolation issues. The approach taken here is very similar to that of several OSGi console implementations. As with those systems, there are a number of pros and cons.

Pros:

• Contributing new actions is relatively easy.

• Contributed actions can be consumed by any number of subsystems in any way they choose.

• Using DS, the contributing bundles need not be started for action contributions to be recognized.

• The actions can be POJOs and so are testable using standard testing techniques.

Cons:

• In this example, it is the action providers, the producers, that determine the relative positioning of the actions.

• Internationalization of the action labels is not directly supported.

• The OSGi service registry is not scoped. As a result, it does not directly support multiple portals running in one framework having different sets of actions or the simultaneous use of the action service interface in other contexts.

• Actions contributed to the portal may be used by unintended consumers.

In the end, none of these individual topics should drive your adoption or rejection of the approach. In some cases a pro is a con and vice versa. The needs of your system should drive the mechanism you choose. For more discussion of module collaboration, see Chapter 15, “Declarative Services,” and Chapter 16, “Extensions.”

13.6 Summary

In this chapter we added an extensible web-based UI portal to the Toast Back End. The portal uses the Whiteboard Pattern to enable the contribution of new UI actions and content. Using the Whiteboard Pattern makes it easy for portal contributors to add functionality but introduces some subtleties that need to be handled by the portal.

As we saw, overall it was quite straightforward to add an extensible web UI to Toast. The example portal is simplistic but suitable for our purposes. From these modest beginnings it is easy to see how you can benefit from the same modular approaches used in RCP development when building the back end UI. Technologies such as Rich Ajax Platform take this a step further and enable rich server-side UIs using client-side programming models.

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

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