Accessing remote systems
The portlet API provides a ContentAccessService, which allows portlets to access remote systems or content from remote URLs, including URLs located on the other side of a proxy server. You should always use this service to access remote content if you cannot be certain whether a firewall will be present after the portlet is deployed into a production environment.
See Portlet services for an overview of portlet services and how to access them.
Standard portlet example
The following example shows how a standard portlet uses the content access service to set up an HTTP input stream to a remote system. In this example, the method receives the URL to the backend system as a String (urlS). If the service cannot be found by JNDI, this sample writes a message to the log. However, standard portlets should always provide equivalent functionality when the portlet service cannot be located.
import com.ibm.portal.portlet.service.*;
import com.ibm.portal.portlet.service.contentaccess.*;
...
private PortletServiceHome casHome = null;
...
public void init(PortletConfing config)
{
javax.naming.Context ctx = new javax.naming.InitialContext();
try {
Object home =
ctx.lookup("portletservice/com.ibm.portal.portlet.service.contentaccess.ContentAccessService");
if (home != null)
casHome = (PortletServiceHome) home;
} catch(javax.naming.NameNotFoundException ex) {
// if service is not available, write to the log
config.getPortletContext().log("Content Access Service is not available");
}
}
protected InputStream getHTTPInputStream(String urlS, PortletRequest request,
PortletResponse response) throws IOException {
getPortletConfig().getPortletContext().log("getHTTPInputStream: " + urlS);
if (casHome != null)
{
ContentAccessService contentAccessservice = (ContentAccessService) casHome.getPortletService
(ContentAccessService.class);
// content access service handles local and remote URLs transparently
return contentAccessservice.getInputStream( urlS, request, response );
} else
{
// no content access service available
return (new URL(urlS).openStream);
}
}
The ContentAccessService can also open an SSL connection to remote applications. The code is the same as for nonsecure connections (see Figure 1) except that you specify a secure protocol (HTTPS) in the URL. However, the portal must be configured to support SSL in PortletServiceRegistryService.properties.
IBM example
import org.apache.jetspeed.portlet.service.ContentAccessService;
...
protected InputStream getHTTPInputStream(String urlS, PortletRequest request,
PortletResponse response)
throws MalformedURLException, IOException {
if(getPortletLog().isInfoEnabled()) {
getPortletLog().info("getHTTPInputStream: " + urlS);
}
try {
PortletContext context = getPortletConfig().getContext();
ContentAccessService contentAccessservice =
(ContentAccessService)context.getService(org.apache.jetspeed.portlet.service.
ContentAccessService.class);
} catch(PortletServiceException e) {
getPortletLog().error("MyPortlet: ContentAccessPortletService error: ",e);
throw new IOException("ContentAccessPortletService Error: " + e);
}
}
getMarkup and character sets
The getMarkup() and include() methods in ContentAccessService require a website to return the character set used to encode the content; this information is normally included in the HTTP response headers. However, sometimes websites do not specify the character set. In this case, ContentAccessService assumes the content is encoded with UTF-8. However, if the website contains non-English content (for example, double-byte character languages such as Japanese and Korean), content will not render properly.
InputStream stream =
contentAccessService.getInputStream(url, portletRequest, portletResponse);
Reader reader = new InputStreamReader(stream, mySpecifiedCharset);