Tuesday, 30 September 2014

Integrating connection portlets with web sphere portal server

The IBM® Connections portlets render social data from IBM Connections in the WebSphere Portal environment, and IBM strategically promotes the integration of Connections with WebSphere Portal using IBM Connections portlets. Customers and Business Partners can download the IBM Connections 3.x Portlets for WebSphere Portal from theBusiness Solution Catalog and customize them per their requirements.

The portlet application bundles portlets for nearly all services provided by the Connections server (Activities, Blogs, Bookmarks, Forums, Profiles, Wikis, and Tag Cloud), most of which have two flavors of portlets: 

The details portlet, which provides full-fledged read, write, and edit capabilities and is used to perform all major functionalities offered by the service.

There are also the summary portlets, which provide a read-only snapshot of the service and redirect the user to the details portlets for any write, edit, or advanced functions.

Connections portlets consume the Representational State Transfer (REST) services from the Connections server for integration, and they use IBM Web Experience Factory (WEF) as a development environment.

This article describes the authentication mechanisms used with the Connections server that are supported by portlets. The article not only describes the use case of Connections portlets but also can serve as a reusable asset for technical developers for other similar implementation scenarios. 

We begin with how SSO is used by the portlets with WebSphere Portal Ajax Proxy and also cover basic authentication and its use with AJAX proxy in WebSphere Portal. Since the Connections portlets use WEF as the tool for portlet application development, we also discuss implementation methods using WEF for both authentication mechanisms.


SSO with WebSphere Portal Ajax proxy


The Connections portlets interact with the Connections server by invoking REST APIs exposed by the latter. Since the portlets interact with personalized data on the Connections server, the REST calls have authentication information, as part of the request header, that needs to be provided by the portlets. 

In this section we explain how to implement Single Sign-on (SSO) configured between WebSphere Portal and the Connections server, as well as how to use third-party authentication systems for more advanced configurations.

Configuring SSO


Once SSO is configured between WebSphere Portal and the Connections server and a user logs in to WebSphere Portal, the user is also authenticated to the Connections server; hence, the user is able to view personalized data from the Connections server within WebSphere Portal. 

For SSO to work, both WebSphere Portal and the Connections server need to share a common LDAP. For more information on how to configure this, refer to the Help topic,Enabling single sign-on for the portlets using a stand-alone LDAP server."

To render Connections social data within the portlets, the portlet application code calls REST APIs exposed by the Connections server, using the REST Service Call Builder from WEF. The Builder has various inputs, the primary of which are the REST URL, HTTP method type, URL parameters, request body, request body schema, HTTP cookies, etc. In the Builder input for HTTP Cookies, we can mention the various cookies that need to be used by the builder.

Prior to the 3.0.1 release, the Connections portlets only supported SSO using LTPA tokens, which they did by providing the cookie name and value in the Rest Service builder under the HTTP Cookies section (see figure 1).

Figure 1. HTTP Cookies section of Rest Service Builder


This approach restricted the portlets from passing other third-party authentication cookies used by third authentication mechanisms like TAM and SiteMinder dynamically as the cookie name was not configurable.

To support all the third-party authentication cookies that are supported both by WebSphere Portal and Connections, it makes sense to provide them as part of the configuration that Portal Administrators can set up according to the authentication mechanism used. 

To achieve this, we found that Portal Ajax proxy (application specific) was the best fit as it has an XML configuration file available that lets Administrators configure the cookie names that can be forwarded.

WebSphere Portal provides two types of Ajax Proxy mechanisms:
  • Global proxy. This proxy setting applies at the Portal level and is applicable for every portlet on WebSphere Portal.
  • Application-specific proxy. This is specifically designed for a particular portlet application and takes precedence over the Global proxy.
The Application-specific proxy mechanism was chosen for Connections portlets. Connections 3.0.1.1 portlets have the application-specific proxy defined in the proxy-config.xml file in the portlet .war file under the WEBINF folder. This proxy has the following settings:
  • All the default names of the cookies that are used by the third-party authentication mechanisms and are supported by Portal and Connections.
  • Supports both SSO and Basic authentication.
  • The placeholder for the Connections server URL that can be provided in the Resource Environment provider (REP).
Figure 2 shows a code snippet of the proxy-config.xml file.

Figure 2. Code snippet of proxy-config.xml file


The proxy URL in the proxy-config.xml file is defined in the WebSphere Application Server admin console under Resource environment providers --- WP ConfigService --- Custom properties. The property named must be specified as:
Name: wp.proxy.config.urlreplacement.ibm_connections_policy.default.connections.server.https
and the value as the Connections server URL; for example, https://www.connections.com/*. For more details on this mechanism, refer to Ajax Proxy documentation of WebSphere Portal.

The cookies provided in proxy-config.xml are the default cookies used by TAM (JSESSIONID), SiteMinder (SMSESSION,JSESSIONID), WebSEAL (PD-H-SESSION-ID, PD-S-SESSION-ID), and the regular LTPA cookies (LTPA, LTPA2, LtpaToken, LtpaToken2).

Before the WebSphere Portal Ajax proxy was introduced, any static resource like images was fetched to the client browser by providing the direct URL (https:www.connections.com/profilephoto.do?userid=) of the resource of the Connections server.

Ajax-proxy-enabled portlets fetch resources from the Connections Server through the proxy rather than fetching them directly. To achieve this, an application-specific proxy URL is used to point to the resource. Here is the description of the URL that can be used for any static resource:

http://proxy/https/
for example:
To fetch a resource on an anonymous page, "proxy" is used and is replaced by "myproxy" in cases where the page is authenticated.

Developing using WEF


The REST Service Call Builder in WEF doesn't use a proxy to connect to the REST service, so we’ve extended the REST Service Call Builder to make the REST call, using the Portal Ajax Proxy object.

A Java class, such as LCURLConnectionFactory, is written to locate and return the Portal Ajax Proxy object. This class implements the com.bowstreet.util.HttpURLConnectionFactory interface of the REST Service Call Builder.

In order for the REST Service Call Builder to use this class for connecting to the REST URL, we must add the property, wpf.httpURLConnectionFactory.class, with the value set to the name of the above class in the override.properties file, under the WEB-INF/config directory of the Web Experience Factory project, like this:

wpf.httpURLConnectionFactory.class=com.ibm.lconn.lcaccelerator.util.LCURLConnectionFactory
The LCURLConnectionFactory class overrides the createConnection and postProcessConnection methods defined in the com.bowstreet.util.HttpURLConnectionFactory interface. The overridden createConnection method is called every time a REST Service call is made to any URL through the REST Service Call Builder.

When an application-specific proxy configuration is used, the code snippet in listing 1 is used to locate the application's AJAX Proxy object.

Listing 1. Code to locate Ajax Proxy object


 HttpURLConnection conn = null;
PortletAjaxProxyService _papsPortlet=null;
Context ctx = newInitialContext();
Name myjndiname = newCompositeName(PortletAjaxProxyServiceHome.JNDI_NAME);
Object obj = ctx.lookup(myjndiname);
 if(obj instanceofcom.ibm.portal.resolver.proxy.service.PortletAjaxProxyServiceHome)
                        {
      PortletAjaxProxyServiceHome papsh= (PortletAjaxProxyServiceHome)obj;
      _papsPortlet= papsh.getAjaxProxyService((PortletRequest)webAppAccess.getHttpServletRequest().getAttribute(Constants.PORTLET_REQUEST),
                                                (PortletResponse)(webAppAccess.getHttpServletRequest()).getAttribute(Constants.PORTLET_RESPONSE));
 
} else      {
                        com.ibm.wps.resolver.proxy.service.PortletAjaxProxyServiceHomeImpl papsh = (com.ibm.wps.resolver.proxy.service.PortletAjaxProxyServiceHomeImpl)obj;
_papsPortlet= papsh.getAjaxProxyService((PortletRequest) webAppAccess.getHttpServletRequest().getAttribute(Constants.PORTLET_REQUEST)
                                                , (PortletResponse) webAppAccess.getHttpServletRequest().getAttribute(Constants.PORTLET_RESPONSE));
}
conn =(HttpURLConnection)_papsPortlet.createConnection(baseURL);


If the Ajax Proxy Service object is not retrieved, that is, the application proxy config file is not available in the portlet .war file, it returns the default URL Connection object to the REST Service Call Builder:

HttpURLConnection conn = (HttpURLConnection)baseURL.openConnection();
Before returning the object to the REST call service, the available request headers should also be copied into the Connection object being returned.

Similarly, the postProcessconnection method defined in the com.bowstreet.util.HttpURLConnectionFactory interface can be overridden. This method is called every time after a REST Service call is made to any URL through the REST Service Call builder.

The purpose of this method is to do any additional processing required after the REST Service is made, and to attempt to disconnect the connection, if it is already connected. It can be used to see the logs to determine the response code, response message, and how long that request has taken to serve, etc.

Troubleshooting

  • “HTTP Status 403.” This error message usually occurs when the proxy is not allowing access to the URL. Verify that the proxy is configured to allow access to the URL, and check the URL defined in the Resource environment provider in wpconfig service.
  • “HTTP Status 504.” This occurs upon a timeout. You can increase the timeout value by changing the value of "socket-timeout" in the proxy-config.xml.

Basic authentication support for IBM Connections portlets


The Connections portlets aim to provide a user experience similar to that of the IBM Connections server within the Portal environment. In native IBM Connections, the user logs in only once to access all services provided by IBM Connections.

Since the portlets are individual application windows over Portal, we required a similar user experience whereby users enter their credentials for one service portlet, and all other service portlets share the credentials to show personalized data for various Connections services.

In earlier, pre-3.0.1.1 versions of Connections portlets, the user had to personalize every portlet with their credentials, which was a limitation since the user needed to put the same credentials repeatedly in every portlet.

In version 3.0.1.1, users need to enter their credentials only the first time in any of the portlets, and these credentials are used by other portlets subsequently. The WebSphere Portal Credential Vault infrastructure (described below) is used to store and retrieve the credentials for this scenario.

Using WebSphere Portal Credential Vault infrastructure


As of version 3.0.1.1, the Connections portlets offer two flavors of Credential Vault usage:

(1) Shared user slot
This enables every user to set their own credentials and see their personalized social content in the Connections portlets. A separate Credential Vault slot is created for every user, and the credentials are shared across all the Connections portlets accessed by that user.

The user must set the credentials by accessing the personalize mode of any one service portlet, after which all other service portlets retrieve the credentials stored in the shared user slot. In this way, we are able to provide a Portal user experience whereby users can access all services of IBM Connections by setting credentials for a particular service.

By default, the personalization user interfaces (for instance, the personalization form) are not enabled. To enable this feature, administrators must set the "authenticationMethod" value in the lcaccelerator.properties file to "basicAuth". The file is in "WEB-INF\lcaccelerator\properties" of the installed portlet application.

To change the credentials, simply enter the new credentials in the personalize window (see figure 3) on any portlet, and the new credentials will be applied to all the Connections portlets. To delete the credentials, simply clear the credentials and save.

Figure 3. Personalize window


(2) System slot
This enables the Portal administrator to configure a particular portlet with a credential that is valid for all users. The administrator must configure the portlet with a system slot, which is created through the Portal administration console. To use this feature, the administrator performs the following steps:

  1. Set the "authenticationMethod" value in the lcaccelerator.properties file to "basicAuth". The file is found in "WEB-INF\lcaccelerator\properties" of the installed portlet application.
  2. Create a system slot with the credentials through the Portal administration console. Details are provided in the Infocenter topic, “Enabling basic authentication.”
Thereafter, the configuration mode of the portlet would show the system slot created above, and Administrator needs to select the system slot from the drop-down menu (see figure 4). Note that, in this scenario, all portlet instances for the particular portlet would be configured for using the credentials from the system slot.
Figure 4. Select a system slot



Administrators must perform similar steps in the config window for other portlets. For example, if the Blogs portlet is configured with a particular System slot, then all Blogs portlet instances across the portal will use the same slot to render the personalized data for all users.

Also note that, in cases in which credentials are set through both the shared user slot (using personalize mode) and system slot (using configure mode), the shared user slot is given precedence over the system slot.

Developing using WEF


Connections portlets use the REST Service Call Builder to make HTTP requests to the Connections REST API for publishing and retrieving data. There are no direct Builder inputs in this Builder that reference any Credential Vault resources. To use the Portal Credential vault with the REST service Builder, we implemented a Linked Java Object (LJO) for creating and extracting passive Vault slots.

Adding Credential Vault slot to the proxy URL


We set the Credential Vault to the proxy URL by adding the parameter, hpaa.slotid, set to the value of “slotid”. After this parameter is set in the URL, the following entry is required in the proxy-config.xml file to pass the slot id for authentication:


<proxy:meta-data>
            <proxy:name>forward-credentials-from-vault</proxy:name>
            <proxy:value>true</proxy:value>
</proxy:meta-data>

In the absence of this metadata in the proxy config definition, the specified hpaa.slotid parameter will not be processed. In addition, basic-auth-support should also be set to "true" for the proxy policy definition of the specific Connections server in proxy-config.xml (see figure 5).

Figure 5. basic-auth-support set to "true"


To verify that the portal proxy is configured to pick the credentials from the Credential Vault slot id and use it to authenticate to an external server URL, use the test URL for the form:

http://localhost:10039//myproxy/http/&hpaa.slotid=
We should get an authenticated response after credentials are selected from the credential slot. Note that we need to log in to WebSphere Portal with the user to whom the slot id belongs and map the security role, "AllAuthenticatedUsers", to appropriate users/groups of the application.

Obtaining the slot ID


Connections portlets supports shared user slots (per user, all resource) and System slots (all users, per resource) as described in Section 3.1 above. A shared user slot is created when a user specifies the credentials in the Personalize mode of the portlet, using Credential Vault APIs.

If the user changes the credentials, then the credential slot is updated for all the resources. If the user deletes the credentials from the Personalize mode and a slot exists for that user, then the slot is also deleted.

When a user enters the credentials from the Personalize mode and clicks the Save button, the slot for that user is searched by use of the code snippet in listing 2.

Listing 2. Code for searching for slott


Context ctx = new InitialContext();
              PortletServiceHome cvsHome = (PortletServiceHome)ctx.lookup("portletservice/com.ibm.portal.portlet.service.credentialvault.CredentialVaultService");
              if (cvsHome != null) {
              CredentialVaultService  service = (CredentialVaultService)cvsHome.getPortletService(CredentialVaultService.class);
            
for(Iterator it = service.getAccessibleSlots(request); it.hasNext();)
            {
                CredentialSlotConfig config = (CredentialSlotConfig)it.next();
                              
                if(config.getResourceName().startsWith(slotResourceName))
                {
                    slotIdTemp = config.getSlotId();                   
                   
                }
            }


In the above snippet the resource name for the Connections portlet is set to “lcPortlets_CredentialVaultResourceName” (though it can be changed). One resource name suffices here since the shared user slot means per user all Connections services.

If the user is entering the credentials for the first time, then no slot will be found, and the new slot is then created using code snippet in listing 3.

Listing 3. Code for creating new slot


CredentialSlotConfig slot = null;

Context ctx = new InitialContext();
              PortletServiceHome cvsHome = (PortletServiceHome)ctx.lookup("portletservice/com.ibm.portal.portlet.service.credentialvault.CredentialVaultService");
              if (cvsHome != null) {
              CredentialVaultService  service = (CredentialVaultService)cvsHome.getPortletService(CredentialVaultService.class);
       
        ObjectID segmentID = service.getDefaultUserCredentialSegmentId();
        HashMap descriptionsMap = new HashMap();
        HashMap keywordsMap = new HashMap();
        int secretType = CredentialVaultService.SECRET_TYPE_USERID_STRING_PASSWORD_STRING;
        //boolean bActive = true;
        boolean bActive = false;
        boolean bPrivate = false;
        
        //Creating slot
        slot= service.createCredentialSlot(slotResourceName, segmentID,descriptionsMap,keywordsMap, secretType, bActive, bPrivate, request);
         slot.getSlotId();

service.setCredentialSecretUserPassword(slot, usedId, password.toCharArray(), request);

Now, the next time a user goes into the Personalize mode and updates the credentials, the above snippet can again be used to update the credentials to a new value. However, if the user deletes the credentials now, then the slot must be deleted, using this snippet:

service.deleteCredentialSlot(slotId);
3.4.1 Working with system slots
System slots are defined for all users and all resources, so the configure mode of the portlet is best suited to selecting the system slot. We create system slots by using the Credentials Vault admin portlet, per the product documentation topic, “Enabling basic authentication.” After the slots are created, we can load them by using this snippet:

ArrayList systemSlotList = CredentialVault.getSystemSlotsName(request, vaultService);
After a user selects the system slot in configure mode and saves it, the slot id is saved in the Portlet Preferences.

Using Reps and shared library in J2ee or portal applications

Generally speaking, deploying a typical Web application usually consists of deploying a single .ear (or .war) file, first in an integration test environment, then in a test environment, and finally in the production environment. Environment-specific variables, important for executing the application properly at each stage in the deployment process, can be stored either as key value pairs in properties, as env-entries in web.xml, or as lookup values in a relational database. Whether storing these application variables in a relational database is a good idea or not is subject to some debate. However, storing the application variables in properties files (or in deployment descriptors) requires that you modify the properties files (or the deployment descriptors) after they have already been deployed to tailor these variables for each particular environment, or write scripts to use different sets of files during application packaging time. In all cases, these files are necessarily different across different environments.
While making changes to the deployed files (properties files or web.xml) after deployment can be error prone (making changes in a multi-node clustered system can be even more error prone), whether or not this procedure is acceptable depends on your organization's guidelines. Regardless, as an alternative to this generally undesirable practice, you can use the resource environment provider to avoid and eliminate the problems mentioned above: by configuring such application dependent variables as resource environment entries, you can administer them using the WebSphere Application Server administrative console -- without having to resort to modifying deployed files.
This article explains how to create a resource environment provider, referenceable objects, and custom properties, plus how to administer the custom properties in the WebSphere Application Server administrative console, and how to access these properties in the application.
This article assumes a good understanding of Java™ programming, WebSphere Application Server V6 administration, and J2EE™ technologies.

Resource environment provider

WebSphere Application Server Versions 5.x and 6.x support the referencing of a resource environment reference, which is similar to referencing other already supported resource references, such as a DataSource, QueueConnection factories, and so on, and is accessible through JNDI lookups. While the classes for DataSource, QueueConnection factories, and others, are predefined in WebSphere Application Server, you must create the classes required for referencing a resource environment provider yourself.
At a minimum, two classes are required to use the resource environment provider in an application: a factory class, and a class that provides custom properties. It is mandated that the factory class implement the interface javax.naming.spi.ObjectFactory. The method getObjectInstance(...) returns the class holding the custom properties. With the help of these two classes and the administration support provided by WebSphere Application Server, we can convert the properties defined in the properties file (or in a deployment descriptor file) into managed variables, and administer them through the WebSphere Application Server administrative console. Once these managed variables can be managed through the admin console, any environment-specific variable can be administered through the console, and the need to alter the deployed properties files or to create environment-specific properties files is eliminated. With this approach, each environment uses the same deployed files.

Sample implementation

An example will help explain these concepts. The example we will look at uses two classes:
  • ConfigFactory
  • Config
Listings 1 and 2 show the code for both of these.
Listing 1. ConfigFactory.java
package com.ibm.acme.ree.lib;
import java.util.Enumeration;
import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.Name;
import javax.naming.NamingException;
import javax.naming.RefAddr;
import javax.naming.Reference;
import javax.naming.spi.ObjectFactory;

public class ConfigFactory implements ObjectFactory
{
 private static Config config = null;
 public Object getObjectInstance(
  Object object,
  Name name,
  Context nameCtx,
  Hashtable environment)
  throws NamingException
 {
  if(config == null)
  {
   config = new Config();
   Reference ref = (Reference) object;
   Enumeration addrs = ref.getAll();
   RefAddr addr = null;
   String entryName = null;
   String value = null;
   while (addrs.hasMoreElements())
   {
    addr = (RefAddr) addrs.nextElement();
    entryName = addr.getType();
    value = (String) addr.getContent();
    config.setAttribute(entryName, value);
   } 
  }
  return config;
 }
}
Listing 2. Config.java
package com.ibm.acme.ree.lib;

import java.util.HashMap;
import java.util.Map;

public class Config
{
 private Map attributes = null;
 public Config()
 {
  attributes = new HashMap(10);
 }
 protected void setAttribute(String attributeName, String attributeValue)
 {
  attributes.put(attributeName, attributeValue);
 }
 public Object getAttribute(String attributeName)
 {
  return attributes.get(attributeName);
 }
}
The caching of the custom properties is illustrated in ConfigFactory.java (Listing 1). Depending on the application requirements, the properties could be made dynamic, thereby avoiding the caching in the above code.
To create and use a resource environment provider in a Web application, you need to:
  1. Create a shared library
  2. Create a resource environment provider
  3. Create a referenceable object.
  4. Create resource environment entries.
  5. Create custom properties.
  6. Create resource environment reference within the Web module.
The sections that follow illustrate these steps.

1. Create a shared library

Create a simple shared library so that the classes can be used for all applications hosted on the server. WebSphere Application Server provides a wizard to do this:
  1. Compile the two classes, Config.java and ConfigFactory.java, and create a JAR file, named reelib.jar.
  2. Copy the JAR file to a location of your choice, such as C:\temp\.
  3. From the WebSphere Application Server administrative console, expand Environment => Shared Libraries.
  4. Set the library Scope to Cell, then select New (Figure 1).
    Figure 1. Set shared library scope
    Figure 1. Set shared library scope
  5. Enter a Name for the library: ree_lib.
  6. Enter a text Description and a Classpath name for the library, then select Apply (Figure 2).
    Figure 2. Define shared library
    Figure 2. Define shared library
  7. Save changes to complete the library creation. The new library will be listed, as shown in Figure 3
    Figure 3. Available shared library listing
    Figure 3. Available shared library listing

2. Create a resource environment provider

To create a resource environment provider:
  1. From the administrative console, select References => Resource Environment => Resource Environment Providers (Figure 4).
    Figure 4. Create Resource environment provider
    Figure 4. Create Resource environment provider
  2. Set the Scope level to Cell, then select New (Figure 5).
    Figure 5. Create new resource environment provider
    Figure 5. Create new resource environment provider
  3. Name the resource environment provider MyResourceEnvironmentProvider, enter a Description for the resource, then click OK (Figure 6).
    Figure 6. Define resource environment provider
    Figure 6. Define resource environment provider
  4. Save changes.
When complete, the newly created resource environment provider will be listed in the display (Figure 7).
Figure 7. Available resource environment provider
Figure 7. Available resource environment provider

3. Create a referenceable object

A "referenceable" is the object defining the relationship between the factory class and the class holding the custom properties. To create a referenceable:
  1. From the administrative console, expand Resources => Resource References => Resource Environment Providers.
  2. From the Resource environment providers panel (Figure 8), select the provider you just created, MyResourceEnvironmentProvider.
    Figure 8. Select resource environment provider
    Figure 8. Select resource environment provider
  3. Select Referenceables (Figure 9).
    Figure 9. Resource environment provider detail
    Figure 9. Resource environment provider detail
  4. Click on New.
  5. The classes defined earlier, com.ibm.acme.ree.lib.ConfigFactory and com.ibm.acme.ree.lib.Config, are used to create Referenceables. On the Referenceables dialog (Figure 10), enter fully qualified class names for Factory class (com.ibm.acme.ree.lib.ConfigFactory) and Class name (com.ibm.acme.ree.lib.Config), then select OK. The defined referenceable will then display, as shown in Figure 11.
    Figure 10. Define referenceable
    Figure 10. Define referenceable
    Figure 11. Defined referenceables
    Figure 11. Defined referenceables
  6. Save changes.

4. Create resource environment entries

About variable names
If you use different names to define any elements than those used in these examples, be sure to note them and substitute them where appropriate throughout these instructions.
A resource environment entry enables access to the resource by reference via JNDI lookup. To define a resource environment entry:
  1. From the administrative console, expand Resources => Resource Environment => Resource Environment Providers => MyResourceEnvironmentProvider.
  2. Select Resource environment entries (Figure 12).
    Figure 12. Resource environment provider detail
    Figure 12. Resource environment provider detail
  3. On the next dialog, select New (Figure 13).
    Figure 13. Create new resource environment entry
    Figure 13. Create new resource environment entry
  4. On the Configuration dialog (Figure 14), enter values for Name (MyResourceReference) and JNDI name (rep/dev/app1/MyResourceReference). This JNDI name is used during application deployment resource reference mapping.
    Figure 14. Configure resource environment entry
    Figure 14. Configure resource environment entry
  5. Click OK, then save the changes.
    Figure 15. Defined resource environment entry
    Figure 15. Defined resource environment entry

5. Create custom properties

To define the custom properties that would be used in the application:
  1. From the administrative console, expand navigate to Resources => Resource Environment => Resource Environment Providers => MyResourceEnvironmentProvider => Resource Environment Entries => MyResourceReference.
  2. Select Custom properties (Figure 16).
    Figure 16. Select custom properties
    Figure 16. Select custom properties
  3. Select New. (Figure 17)
    Figure 17. Create new custom properties
    Figure 17. Create new custom properties
  4. Enter values for the Name (MyVariable), Description, Type, and Value fields, then OK. (Figure 18)
    Figure 18. Define custom property
    Figure 18. Define custom property
    Figure 19. Defined custom properties
    Figure 19. Defined custom properties
  5. The custom property you defined appears in the custom properties list (Figure 19). Repeat step d to add additional variables.
Notice that the wizard provided by WebSphere Application Server does not provide an option to specify the required attribute, although it defaults to false. Through WebSphere admin scripting, you can specify a value for the required attribute. If you are running a standalone application server, or if it is a member in a cluster, the new resources you defined are available after restarting the application server.

6. Create resource environment reference within the Web module

Similar to accessing any resource within a container, to access the resource reference entries, you have to declare a reference within the Web module or EJB module, as appropriate. To create a resource reference using IBM Rational® Application Developer:
  1. For a Web module, open the web.xml file (for an EJB module, open the ejb-jar.xml file ) using the deployment descriptor editor.
  2. Click on the References tab, then select Add (Figure 20).
    Figure 20. Deployment descriptor editor
    Figure 20. Deployment descriptor editor
  3. From the Add Reference dialog, select Resource environment reference, then Next (Figure 21).
    Figure 21. Add a reference
    Figure 21. Add a reference
  4. Enter values for Name (MyConstants), Type, and Description, then select Finish (Figure 22).
    Figure 22. Configure resource environment reference
    Figure 22. Configure resource environment reference

Using the resource environment provider elements

This code sample in Listing 3 shows how to access the referenceable and the associated custom properties.
Listing 3. Accessing custom properties
try {
 Context ctx = new InitialContext();
 Object object = 
ctx.lookup("java:comp/env/MyConstants");
 Config config = (Config) config;
 String myVariable = config.getProperty("MyVariable");
} catch (Exception e) {
 // .. Handle Exception e
}
Before you can actually use the resource environment provider you created, you have to define the implementation classes within the application's classpath. This can be done by mapping the shared libraries at application deployment time. We will not show the full application deployment process here, but we will show the necessary steps to map the shared library:
  1. On the Preparing for the application installation dialog, select your WAR file, then check Local file system and Show me all installation options, then Next (Figure 23).
    Figure 23. Prepare application for deployment
    Figure 23. Prepare application for deployment
  2. Continue with the application deployment process, selecting default values (or other values, at your discretion), through installation Steps 1, 2, and 3. When you arrive at Step 4: Map Shared Libraries (Figure 24), check the module you want to select, then click Reference shared libraries.
    Figure 24. Display shared map libraries
    Figure 24. Display shared map libraries
  3. On the Enterprise Applications dialog, select the library you want to add to the application's classpath, ree_lib, then click on the >> button to adds the selected library to the Selected list. Click OK. (Figure 25)
    Figure 25. Select shared libraries
    Figure 25. Select shared libraries
  4. Make sure that the library is added to the application classpath by examining the Shared Libraries column, as shown in Figure 26.
  5. Continue with the application deployment process.
    Figure 26. Map shared libraries
    Figure 26. Map shared libraries
  6. On step 5 of application deployment, Map resource environment entry references to resources, enter the JNDI name of the referenceable (rep/dev/app1/MyResourceReference) into the field Target Resource JNDI Name field.
  7. Continue with the application deployment process.
    Figure 27. Specify resource environment entry
    Figure 27. Specify resource environment entry
After the application has been deployed, you will want to test the application's use of the resource environment provider. To do so, you need to first restart the application. Once started, you can easily verify that the application is taking its value from the resource environment entry, rather than from a property defined in a property file, or from an environment entry defined in web.xml or ejb-jar.xml. Whenever needed, you can alter this variable by changing the value from the WebSphere Application Server administrative console and restarting the cluster members -- all without touching any deployed files, retaining the integrity of the entire application and its processing environments.

Custom single threaded java server

 package com.diffengine.csv; import java.io.*; import java.net.*; import java.util.Date; public class Server { public static void main(Str...