Access 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. We should always use this service to access remote content if we 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.
Figure 1. Example: ContentAccessService
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); } }When accessing remote internet resources directly, the content is simply taken and written to the portlet's output. This means that all relative links to other pages or images will be broken. This can be solved by parsing the content or use some enhanced browser portlet.
The ContentAccessService can also open an SSL connection to remote applications. The code is the same as for nonsecure connections (see Figure 1) except specified a secure protocol (HTTPS) in the URL. However, the portal must be configured to support SSL in PortletServiceRegistryService.properties.
IBM example
The following example shows how a portlet written to the IBM portlet API uses the content access service to set up an HTTP input stream to a remote system. This example is similar to the standard example, except the portlet uses the PortletContext.getService() method to retrieve the portlet service instead of JNDI.
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.
Developers can work around this problem using the getInputStream() method, which handles the character set conversion manually. For example:
InputStream stream = contentAccessService.getInputStream(url, portletRequest, portletResponse); Reader reader = new InputStreamReader(stream, mySpecifiedCharset);
Related information
Parent Portlet creation basics