|
Sun Java Studio Enterprise (hereinafter called Studio Enterprise), is a comprehensive development, deployment, and testing platform that includes the server software and tools in Sun Java Enterprise System. With Studio Enterprise, the process of developing enterprise Web-service applications and deploying them on Java Enterprise System is seamless, intuitive, and straightforward.
This article describes how to use Studio Enterprise 6 2004Q1 to create a portlet--an integration component between an application and your portal--that complies with Java Specification Request 168 Portlet Specification (JSR 168) to access the Google Web service. Also detailed are steps to deploy the portlet on Sun Java System Portal Server (formerly Sun ONE Portal Server and hereinafter called Portal Server).
The major sections in this article are as follows:
Portlet Standards
Over the past few years, portals have evolved rapidly in the Internet space. They have helped businesses aggregate secure and personalized content and applications to the Web, tailored for the audience--customers, suppliers, employees, partners. Portlets used by portals function as pluggable user-interface components that provide a presentation layer to information systems.
In the early days of portal development, little emphasis was placed on component interoperability or reuse. Why? Because portlet APIs for development or customization at that time were limited to a single portal product only.
In 2003, two important standards emerged to address reuse and content portability: Web Services for Remote Portlets Specification (WSRP) and Java Specification Request 168 Portlet Specification (JSR 168). At first glance, both WSRP and JSR 168 may seem to be competing or overlapping standards. In reality, even though they overlap in a few areas and complement each other, WSRP and JSR 168 address different issues. Be sure to note their relationships: these standards represent the direction for portal development in the future.
Introducing WSRP 1.0
WSRP 1.0, approved as an Organization for the Advancement of Structured Information Standards (OASIS) standard in August 2003, defines Web Services Description Language (WSDL) interfaces and semantics for presentation-oriented Web services. Independent of programming languages and platforms, WSRP performs the following functions:
- Enables interactive Web services to be plugged into standards-compliant portals.
- Defines a flexible architecture to decouple aggregation from execution on the
portal.
As WSRP consumers, portals can use or include portlets that are running elsewhere. Portals can also act as WSRP producers and publish their portlets as WSRP services. For portlet developers, WSRP functions in an almost transparent manner--that is, the developers never use WSRP directly.
Introducing JSR 168
Originally proposed by Sun and IBM and released in October 2003, JSR 168 defines the APIs that standardize the development of portlets. It performs two major tasks:
- Defines a standard Java technology-based Web component model for portlets in portal servers that are built on the Java platform.
- Enables portability and vendor independence.
However, JSR 168 does not define interoperability of remote portlets. Portlets that are built according to the JSR 168 model work with all Java technology-based portal servers. The portlet described in this article complies with JSR 168.
JSR 168 Features
JSR 168 defines a standard Java portlet API, a portlet container, and the contract between the API and the container.
A Web component that is based on Java technology, a JSR 168 portlet has a life cycle that is managed by the portlet container, which handles the following basics:
- Provides the portlets with the required runtime environment and persistent storage for portlet preferences.
- Processes requests and generates dynamic content.
The generated content is also called a fragment, meaning a piece of a markup language--for example, HTML, XHTML, Web Site Meta Language (WML)--that adheres to certain rules. You can group this fragment with other fragments to form a portal page, as is the normal practice.
FIGURE 1 illustrates the relationships among user agents, the network, the portal, and portlets within a portlet container.
 |
|
FIGURE 1: Relationships Among the Components Within a Portal Container
|
JSR 168 offers numerous useful portal-specific capabilities. Following are a few highlights:
- Portlet modes -- JSR 168 provides three modes for portlet interactions:
- VIEW -- This mode, a mandatory one that's defined by a portlet, renders
markup fragments.
- EDIT -- This optional mode enables changes to per-user settings to customize rendering.
- HELP -- This optional mode displays help information.
You can also customize the modes for additional portlet functionality.
- User profile attributes -- A portlet defines the user-specific attributes it must access in the deployment descriptor. You can edit them to personalize content.
- Window state -- Four window states--normal, maximized, minimized, and custom--are made available to portlets by the portlet container to indicate how much space is being allocated to the content generated by the portlet.
- Security -- Gatekeeping of user access is a function of the underlying Java Web container, which performs role-based authentication and authorization tasks according to the J2EE security model.
- Portlet persistence -- Portlets can store persistent data for users. Preferences are
readable and writable in the action phase but are read-only in the render phase. Usually, you revise user preferences in edit mode.
For portal vendors, developers, and customers, the JSR 168 standardization of many basic functions performed in Java portal servers confers important benefits. For example, the function of connecting content and displaying it within a portal results in enhanced interoperability between portals.
Certain features are out of the scope of JSR 168, however. Examples are content aggregation, layout management, page personalization and configuration engines, and portal administration and configuration. These are vendor-specific features and are handled by portal servers.
Currently, all major portal vendors, including Sun, Oracle, IBM, Vignette, SAP, Sybase, TIBCO and BEA, support JSR 168. Specifically, Portal Server 6.2 supports JSR 168; Studio Enterprise has bundled Portlet Builder as its portlet development tool.
Building-Process Steps
Studio Enterprise 6 2004Q1 is a comprehensive development platform for Sun Java Enterprise System, consisting of Sun Java Studio Standard 5 (hereinafter called Java Studio), bundled with a complete deployment and testing environment that includes the server software and tools in Java Enterprise System. It serves as the development environment for this build process.
The portlet example in this article uses Google Web-service APIs to perform a Web search through the Simple Object Access Protocol (SOAP). The development process comprises four major steps:
- Generate a Google Web-service client based on a WSDL file from Google. Test its behavior.
- With Portlet Builder of Studio Enterprise, create a portlet application with a portlet that invokes Google's Web service through the Web-service client.
- Verify the behavior of the portlet by viewing the demonstration and simulating the portlet.
- Package the portlet application into a Web archive (WAR) file and deploy it on Portal Server.
Before Step I: Preparing for the Process
Before you begin to build your portlet, do the following:
- Set up your environment.
Install the development environment for Studio Enterprise 6 2004Q1. You can download a trial copy for free. Follow the installation instructions that accompany the software.
Installing Studio Enterprise also installs Java Web Services Developer Pack,
Sun Java System Identity Server, Portal Server, and other Sun Java System server software and tools.
- Download a copy of the Google Web-service WSDL file (
GoogleSearch.wsdl). Save it to a location in the local directory in which you plan to place the Web-service client.
This XML file describes the Web service and is required for passing messages to and from the service with SOAP. By using a set of APIs from Google, Web applications can dynamically make calls to the Google search engine by means of SOAP.
- Register with the Google Web API service.
Follow the directions in point 2 on the "Develop Your Own Applications Using Google" page. You must create a Google account and obtain an authentication key, which will be sent to you by email. The key serves as an input parameter for each of the Google method calls.
Step I. Generating and Testing a Web-Service Client
The Google search portlet in this example depends on a Web-service client that contains stub files and handlers to enable the portlet to invoke the operations through the Google Web-service endpoint.
Follow these steps to create the client that's derived from the Google Web-service WSDL file:
- Start Studio Enterprise.
The entire development process in this example occurs within Studio Enterprise.
- Mount the directory in which
GoogleSearch.wsdl resides so that Studio Enterprise includes the directory in the CLASSPATH environment variable. Do the following:
- From the main window's File menu, choose Mount Directory.
A wizard screen is displayed.
- Select Local Directory.
- Within the wizard, navigate to the directory you want to mount, select it, and click Finish.
In this example, the directory is mounted as example-dir/googlews/webservice/.
- Create a Java package for the Web-service client by right-clicking the directory that you just mounted and then choosing Java Package from the New menu.
You are prompted for a name for the new package. In this example, the package is named sample.
- In the Studio Enterprise window, right-click the folder sample. Choose All Templates from New and then choose Web Service Client from Web Services. Click Next.
The wizard opens a template for creating Web-service clients.
- In the template that is displayed, fill in the names for the client and its package,
and then select the option for using the local WSDL file. Click Next.
In this example, the client is named GoogleClient; its package is called sample.
- In the screen for selecting a local WSDL file that is displayed, select the WSDL file that you copied to your local directory. Click Finish.
In this example, the GoogleSearch.wsdl file is the file to select.
Studio Enterprise then creates a Web-service client in the specified package.
- Right-click the client and verify that the SOAP runtime property is set to JAXRPC [Java API for XML-based Remote Procedure Calls].
The portlet makes remote calls to the Web service with JAX-RPC.
- To generate the client files, right-click the
GoogleClient node and choose
Generate Client Files from the floating menu.
Java Studio parses the WSDL file and generates two set of files:
- SOAP documents -- These documents contain a test client--a simple page based on the JavaServer Pages (JSP) technology--with which you can invoke the operations for a quick test.
- Class files in the subdirectory
GoogleClientGenClient -- These client-side
implementation classes include stub files, which enable the portlet to obtain a handle to the Google Web-service endpoint and then invoke the operations that are exposed through the WSDL file. See FIGURE 4.
 |
|
FIGURE 4: Icon for Web-Service Client
|
- Now test the Web-service client. Right-click the
GoogleClient node and choose
Execute.
Studio Enterprise deploys the Web-service client on the default Web container, which, in this example, is the bundled Tomcat server. The screen for inputting parameters for keyword searches is displayed.
- Copy your Google authentication key and paste it in the key text field and then fill in the other text fields, as appropriate. Click Invoke.
FIGURE 6 is an example of the keyword search results.
If you are working behind a firewall, add the proxy settings, as follows:
- Select the Runtime tab. Choose Installed Servers from the Server Registry menu and then Tomcat from the Installed Servers submenu.
- Right-click the Internal Tomcat (
JWSDP 1.0_01) node and select Properties.
The Properties screen is displayed.
- Add the following arguments under External Execution Process (all on one line):
-Dhttp.proxyHost=your_proxy_hostname -Dhttp.proxyPort=your_proxy_portnumber
- Restart the Tomcat server to enable the changes to take effect.
Step II. Creating a Portlet Application and a Portlet
The Portlet Builder plugin in Studio Enterprise generates templates for portlet applications and portlets and provides a simulation environment for the Portal Server desktop. A portlet application, always Web-based, contains portlets and a portlet deployment descriptor in addition to Java Servlets, JSP pages, HTML pages, classes, and other resources that are normally found in Web applications.
This section describes how to develop a portlet application and a portlet with Portlet Builder. The procedure consists of these steps:
- Create a portlet application.
- Add Web-service client classes.
- Create a portlet.
Creating a Portlet Application
First, create a directory for the portlet application. In this example, the directory is named portlet under the example_dir/googlews directory. Afterwards, mount the directory portlet in Studio Enterprise and then do the following:
- Right-click the
portlet node and then choose All Templates from the New menu.
The screen for selecting templates is displayed.
- Select Portlets under Sun Java System Portal Server Components and then Portlet Application under Portlets.
See FIGURE 7.
- Click Next.
A screen with a Directory text field is displayed.
- Type in the Directory text field the name of the directory in which to place the portlet application module.
In this example, that directory is called example-dir/googlews/portlet.
- Click Finish.
Studio Enterprise creates a portal application template. See FIGURE 8.
 |
|
FIGURE 8: Portlet Application Template
|
The portlet application follows the same directory hierarchy structure as the Web applications. In addition, the application must contain a portlet.xml file in the
WEB-INF directory, which includes the declaration for all the portlets in the application.
Adding the Web-Service Client Classes
Before creating a portlet and adding it to the portal application, you must first copy to the portal application the Web-service client classes used by the portlet. Do the following:
- Expand the
portlet node, select the WEB-INF directory, and then select the Classes node.
- Right-click the
Classes node and choose Java Package from the New menu.
- Name the new package
sample and click Finish.
- Copy the entire
GoogleClientGenClient directory from the Web-service client
directory to the newly created sample package.
FIGURE 9 shows the directory structure.
 |
|
FIGURE 9: Directory Structure for sample
|
Creating the Portlet
To create the portlet, do the following:
- Right-click the
sample package and choose All Templates from the New menu.
Then choose Sun Java System Portal Server Components from the All Templates submenu.
- Choose Portlet Extending GenericPortlet under Portlets.
See FIGURE 10. The GenericPortlet superclass provides a default implementation for the portlet interface.
 |
FIGURE 10: Selection of Portlet Extending GenericPortlet as a Default Implementation for the Portlet InterfacesClick to enlarge
|
- Name the portlet
GoogleSearchPortlet. Click Finish.
Portlet classes, utility classes, and other resources that are accessed through the portlet application class loader must reside within the WEB-INF/classes directory or within a Java archive (JAR) file in the WEB-INF/lib directory.
FIGURE 11 shows the directory structure for WEB-INF/classes after Studio Enterprise has created the GoogleSearch portlet.
 |
|
FIGURE 11: Directory Structure for WEB-INF/classes with Portlet Resources
|
Double-click the GoogleSearchPortlet file to browse it in the Studio Enterprise
Editor: You will find the default implementation that overrides processAction(),
doView(), doEdit(), and other render methods in the GenericPortlet superclass.
Step III. Viewing the Demonstration
To view the demonstration included in this example, unzip this version of GoogleSearchPortlet into the
WEB-INF/classes/sample subdirectory under example_dir/googlews/portlet/. That version contains the source files of the
following:
- The completed
GoogleSearchPortlet class -- This class invokes the GoogleProxy class to access the Google Web service. The GoogleProxy class in turn invokes the methods in the generated stub classes to use the JAX-RPC runtime through the javax.xml.rpc.Stub class.
- Two helper classes for the portlet --
- For distinction, the
sample.GoogleProxy helper class serves as a local proxy to invoke the Web-service methods on the generated Java classes in the GoogleClientGenClient subdirectory.
- The
sample.DisplayElement helper class wraps the search result item as a serialized object for display.
See FIGURE 12.
 |
|
FIGURE 12: Helper Classes for the Portlet
|
GoogleSearchPortlet overrides four methods:
init()
doView()
doEdit()
processAction()
Overriding the init() method. GoogleSearchPortlet overrides the init() method to call the GenericPortlet.init() method so as to register the configuration and obtain the initial parameter for the portlet. Following is the code for init().
public void init(PortletConfig config) throws PortletException {
super.init(config);
key = config.getInitParameter("google.key");
if (key == null) {
throw new UnavailableException("GoogleSearchPortlet -
web services licence key not found!");
}
}
|
GoogleSearchPortlet passes google.key, the initial parameter set in the
portlet.xml file, as the input parameter for each call to the Google Web service.
Overriding the doView() method. GoogleSearchPortlet overrides the
doView() method to do the following:
- Instantiate an instance of the
GoogleProxy class to gain access to the Google Web service port.
- Obtain the parameter values for the Google Web service methods.
- Invoke the search request.
- Extract the result.
The default implementation of the render() method in portlet.GenericPortlet routes the request to a set of helper methods according to the portlet mode. For example, if that mode is VIEW, then GoogleSearchPortlet invokes the doView() method to render the presentation content. See FIGURE 13.
 |
FIGURE 13: Invocation of the doView() Method to Render the Presentation ContentClick to enlarge
|
Following is the code for doView():
protected void doView(RenderRequest request, RenderResponse
response) throws PortletException, java.io.IOException {
response.setContentType("text/html");
PortletPreferences prefs = request.getPreferences();
String query = request.getParameter("query");
String option = request.getParameter("option");
sample.GoogleProxy gproxy
= new sample.GoogleProxy();
if (option.equals("Spelling Check")) {
String suggestion = gproxy.getSpellingSuggestion(key, query);
request.setAttribute("suggestion", suggestion);
}else {
gproxy.doSearch(key, query);
int count = gproxy.getCount();
double time = gproxy.getSearchTime();
String qstr = gproxy.getQueryString();
DisplayElement[] items = gproxy.getDisplayElements();
request.setAttribute("count", String.valueOf(count));
request.setAttribute("time", String.valueOf(time));
request.setAttribute("qstr", qstr);
request.setAttribute("result", items);
}
PortletRequestDispatcher dispatcher =
getPortletContext().getRequestDispatcher("/searchView.jsp");
dispatcher.include(request,response);
}
|
Overriding the doEdit() method. GoogleSearchPortlet overrides the
doEdit() method, which GoogleSearchPortlet invokes when the portlet mode
is EDIT.
While in EDIT mode, users can revise their profile attributes. In this example, users can select either of the two Google Web service options--Search (search for the query string on the Web) or Spelling Check (check the spelling of the query string)--and set a preferred query as their profile. See FIGURE 14.
Following is the code for doEdit():
protected void doEdit(RenderRequest request,
RenderResponse response)
throws PortletException, java.io.IOException {
response.setContentType("text/html");
PortletPreferences prefs = request.getPreferences();
String option = prefs.getValue("option", "Search");
String query = prefs.getValue("query", "Portlet");
request.setAttribute("option", option);
request.setAttribute("query", query);
PortletRequestDispatcher dispatcher =
getPortletContext().getRequestDispatcher("/searchEdit.jsp");
dispatcher.include(request, response);
}
|
Overriding the processAction() method. GoogleSearchPortlet invokes
the processAction() method to render the content again to reflect the new preference settings. Next, GoogleSearchPortlet stores the customized attributes in a persistent storage. For Portal Server, GoogleSearchPortlet handles the persistence through Sun Java System Directory Server (formerly Sun ONE Directory Server). See FIGURE 15.
 |
FIGURE 15: Invocation of processAction() Method for Rendering of ContentClick to enlarge
|
Following is the code for processAction():
public void processAction(ActionRequest request, ActionResponse
actionResponse)
throws PortletException, java.io.IOException {
PortletPreferences prefs = request.getPreferences();
String option = request.getParameter("option");
String query = request.getParameter("query");
if (request.getPortletMode().equals(PortletMode.VIEW)) {
if(option == null) {
option = prefs.getValue("option", "Search");
}
if(query == null) {
query = prefs.getValue("query", "Portlet");
}
actionResponse.setRenderParameter("option", option);
actionResponse.setRenderParameter("query", query);
}else {
if (request.getPortletMode().equals(PortletMode.EDIT)) {
boolean editOK;
String errorMsg = null;
prefs.setValue("option",option);
prefs.setValue("query", query);
try {
prefs.store();
editOK = true;
}
catch (ValidatorException ex) {
editOK = false;
errorMsg = ex.getMessage();
}
if (editOK) {
actionResponse.setPortletMode(PortletMode.VIEW);
}
else {
actionResponse.setRenderParameter("error",errorMsg);
}
}
}
}
|
In this example, two JSP pages display the search result and the edit form. For details, unzip this file (GoogleSearchJSP.zip) into the portlet directory and view the JSP pages.
In the Studio Enterprise Explorer window, a new directory structure is now displayed. See FIGURE 16.
 |
|
FIGURE 16: Directory Structure of GoogleSearchPortlet
|
Editing the Portlet Deployment Descriptor
Besides the GoogleSearchPortlet class, Portlet Builder creates a declaration file in XML, marked by an icon--a channel box with a red title. The declaration file, called GoogleSearchPortlet.portlet, contains an element that defines the deployment declaration for the portlet.
Portlet Builder places the declaration file in the same location as the GoogleSearchPortlet class. When you simulate or package the portlet's WAR file, Portlet Builder automatically updates portlet.xml in the WEB-INF directory with the information in GoogleSearchPortlet.portlet.
In this example, GoogleSearchPortlet.portlet defines the names of the portlet, the class, and the cache information. Since the portlet uses an initial parameter and user preferences, you must add the following elements to GoogleSearchPortlet.portlet:
- The value for the init parameter
google.key
- A preference attribute called
query
- The modes that the portlet supports, in this case EDIT and HELP
Your declaration file then reads like this (the manual modifications you must make are boldfaced):
<?xml version="1.0" encoding="UTF-8"?>
<!--Portlet deployment descriptor-->
<portlet>
<portlet-name>GoogleSearchPortlet</portlet-name>
<display-name>GoogleSearchPortlet</display-name>
<portlet-class>sample.GoogleSearchPortlet</portlet-class>
<init-param>
<name>google.key</name>
<value>your_key_from_Google</value>
</init-param>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>EDIT</portlet-mode>
<portlet-mode>HELP</portlet-mode>
</supports>
<portlet-info>
<title>GoogleSearchPortlet</title>
</portlet-info>
<portlet-preferences>
<preference>
<name>query</name>
<value>portlet</value>
</preference>
</portlet-preferences>
</portlet>
|
Simulating and Packaging the Portlet
Portlet Builder contains a portlet simulator, a Web-based application that displays a portlet's content in a test harness with which you can test the portlet.
To start the portlet simulator, do the following:
- In the Studio Enterprise Explorer window, select the Portlet Application node and right-click for the floating menu.
- Choose Simulate from Sun Java System Portal Server.
The portlet content is displayed in a separate window. See FIGURE 17.
During simulation, the portlet simulator captures error messages along with debugging tips in two log files: /tmp/portletbuilderapp.log and /tmp/SIMportletcontainer.log. These files also contain the logging information from the portlet API.
Next, package the portlet into a WAR file, which the Portal Server deployment tool can then install on Portal Server. Do the following:
- In the Studio Enterprise Explorer window, select the Portlet Application node and right-click for the floating menu.
- Choose Create Deployer WAR from Sun Java System Portal Server.
The screen for defining WAR file names is displayed.
- Type a name for the WAR file in the text field and click OK.
Deploying the Portlet on Portal Server
You use the Portal Server deployment tool to deploy the WAR file on Portal Server.
Note -- During deployment, ensure that both Portal Server and Identity Server are
running.
Deploying the Portlet Application
First, start the deployment tool by logging in as root and typing at the command prompt (all on one line):
# pdeploy deploy -u uid -w password {-g|-d dn} -p webcontainer_password WAR_filename
Following are the subsequent commands to execute along with examples of the screen input:
# portal_install_directory/bin/pdeploy deploy \
-u "uid=amAdmin,ou=People,dc=east,dc=sun,dc=com" -w password -p password \
-g / googlesearch.war
Done Updating Display Profile! Deploying War File to Web Container...
[wdeploy] The war file name is /var/opt/SUNWps/tmp/portlet/googlesearch.war
[wdeploy] The directory /var/opt/SUNWps/tmp/deploy/web-apps/httpsmyhost.
east.sun.com/googlesearch does not exist. Creating it.
[wdeploy] Deploying web application
[wdeploy] Loading new configuration
[wdeploy] Web application deploy successful
SUCCESS.
|
Creating a Portlet Channel
As a next-to-final step, create a portal channel based on the GoogleSearchPortlet class. Follow these steps:
- Log in to the Portal Server Administration Console.
- Choose Services from the View menu.
A list of services is displayed on the left pane. On the right pane are the organization parameters.
- Select Portal Desktop under Portal Server Configuration and click the arrow next to Portal Desktop.
A list of attributes for the portal desktop is displayed on the right pane.
- Click the Channel and Container Management link.
A list of channels is displayed on the right pane.
- Click the New Portlet Channel button under Channels.
The screen for defining the parameters for a new channel is displayed.
- Type
GoogleSearch in the Channel Name text field and then choose googlesearch.GoogleSearchPortlet from the Portlet list. Click OK.
Portal Server creates the channel.
- Log out of the Administration Console.
Displaying the Portlet on Portal Server
The sample portal as displayed on your browser now shows the newly deployed GoogleSearch portlet channel (see FIGURE 18), capable of accessing the Google Web service.
Troubleshooting
If you cannot access the Google Web service from Portal Server, it's likely because Portal Server is behind a firewall. To resolve that issue, revise your proxy settings to point to the configuration file of the Portal Server's Web container.
For example, add the following configuration to the Java virtual machine options in the server.xml file in the /opt/SUNWwbsvr/https-hostname/config directory:
<JVMOPTIONS>-Dhttp.proxyHost=your_proxy_hostname</JVMOPTIONS>
<JVMOPTIONS>-Dhttp.proxyPort=your_proxy_portnumber</JVMOPTIONS>
Afterwards, save the server.xml file and restart Portal Server.
For error messages and debugging logs on the portlet container and the Portal Server desktop, see the files in the /var/opt/SUNWam/debug directory.
Summary
As this example demonstrates, with Studio Enterprise, you can build standard portlets in the same straightforward manner by which you develop Java technology-based Web applications.
Note -- As a bonus, you can take advantage of the capabilities offered by the integrated stack of server software in Sun Java Enterprise System to implement Single Sign-On (SSO) and other identity management features. For a case study on SSO, see Integrating Blackboard Learning System with Sun Java System Identity Server 6.0, SP1: A Case Study.
References
The following product home pages on Sun Developer Network offer a wealth of developer-oriented resources:
Acknowledgment
Thanks to Gary Wang and Carol Zhang, members of technical staff at Market Development Engineering at Sun, for their testing efforts and invaluable feedback.
About the Authors
Cherry Shu, a member of technical staff at Marketing Development Engineering at Sun, assists independent software vendors with technology adoption, porting, and performance-tuning projects that pertain to the Solaris Operating System and Sun Java Enterprise System.
Marina Sum is a staff writer for Sun Developer Network. She has been writing for Sun for 15 years, mostly in the technical arena.
|
|