Suggested Pages

Monday, April 30, 2012

Web Service with Apache CXF and OpenCMS


The exposing of Web Services from a CMS can be usefull to provide functionality towards external systems. Apache CXF implements JAX-WS API and helps to build services easily in custom applications or in software product as OpenCMS.
The following steps describe how to expose web services using Apache CXF with the assumption that we have already created a module in OpenCMS in the right manner from the console of administration of OpenCMS. Besides there should be configured an Export Point so that when you publish this module, compiled java files are copied to the path <OPENCMS-HOME>/WEB-INF/classes/
In this example you use the credentials of a specific user (username: John, password: Smith) to access the VFS (Virtual File System) of OpenCMS. In this post I don't want to speak of the best approach to access VFS of OpenCMS , but expose a possibile way to access it. Use a single user to access VFS is not a bad practice and giving him a role with particular grant may be a good strategy if your external system interacts with OpenCMS at the same way and you are not interested into different interactions with OpenCMS.

Step 1: Add CXFServlet to web.xml of OpenCMS



<web-app version="2.4" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/j2ee" xsi:schemalocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

    <display-name>OpenCms</display-name>
       ...
    <servlet> 
      <servlet-name>CXFServlet</servlet-name> 
      <servlet-class> 
          org.apache.cxf.transport.servlet.CXFServlet 
      </servlet-class>
      <init-param>
        <param-name>config-location</param-name>
        <param-value>/WEB-INF/cxf-servlet.xml</param-value>
      </init-param>
    </servlet> 
    <servlet-mapping> 
        <servlet-name>CXFServlet</servlet-name> 
        <url-pattern>/services/*</url-pattern> 
    </servlet-mapping>

    <context-param>
        <param-name>OpenCmsServlet</param-name>
        <param-value>/opencms/*</param-value>
    </context-param>
      ...

</web-app>

Step 2: Create WebService inside your OpenCMS module


First of all we need to write an interface AccessResource that we annotate with @WebService. This interface rappresents the contract of the web service.

@WebService
package my.service;

package my.service;

import javax.jws.WebService;

public interface AccessResource {
   public void accessResourceOpenCMS();
}


Afterwards we create the class AccessResourceImpl that implements the interface and then we annotate it with @WebService. We have to specify the attribute endpointInterface ( that describes the class providing the abstract contract of the web service) and the attribute serviceName.
As you can see, i get CmsObject using Guest user, but afterwards i make a login as a specific user: John Smith. This user has been created before in the administration console, providing him role and permission to perform the read of CmsResources.

package my.service;

import java.util.List;

import javax.jws.WebService;

import org.opencms.file.CmsObject;
import org.opencms.file.CmsResource;
import org.opencms.file.CmsResourceFilter;
import org.opencms.main.CmsException;
import org.opencms.main.OpenCms;

@WebService(endpointInterface="my.service.AccessResource",serviceName = "AccessResource")
public class AccessResourceImpl implements AccessResource{

 @Override
 public void accessResourceOpenCMS() {
   try {

   CmsObject initCmsObject = OpenCms.initCmsObject("Guest");
   String loginUser = initCmsObject.loginUser("John", "Smith");
   System.out.println(loginUser);
   List readResources = initCmsObject.readResources("/",CmsResourceFilter.ALL);
   for (CmsResource cmsr:readResources){
    System.out.println(cmsr);
   }
  } catch (CmsException e) {
   e.printStackTrace();
  }
  
 }

}

Step 3: Create the configuration file cxf-servlet.xml


In the web.xml we have indicated the cxf-servlet.xml as the file to put the configurations of the web services. In this file it's declared the attribute serviceClass that defines the contract of the web service and the attribute address that defines where the web service it's exposed.

<beans xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:soap="http://cxf.apache.org/bindings/soap" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemalocation="http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
      http://cxf.apache.org/bindings/soap http://cxf.apache.org/schemas/configuration/soap.xsd
      http://cxf.apache.org/jaxws
      http://cxf.apache.org/schemas/jaxws.xsd">

 

  <jaxws:server address="/access_resource" id="accessResourceOpencms" serviceclass="my.service.AccessResource">
   <jaxws:servicebean>
    <bean class="my.service.AccessResourceImpl">
   </bean></jaxws:servicebean>
  </jaxws:server>
 
</beans>


Step 4: Put Apache CXF library into OpenCMS


Last step is to put Apache CXF libraries into <OPENCMS-HOME>/WEB-INF/lib/
Indipendently if you use JBoss or Tomcat to run OpenCMS , when your container is running, the web service is available at the address http://localhost:8080/opencms/services/access_resource and the WSDL at the address http://localhost:8080/opencms/services/access_resource?wsdl.

Friday, April 27, 2012

Example Custom Widget OpenCMS


Before describing how to write custom widget for OpenCMS, i make a brief summary on the role of widgets in OpenCMS.
OpenCMS uses Widgets to perform interaction between administrators/editors and the CMS. An example of a tipical widget is TextAreaWidget. This widget allows editors to insert long descriptions inside a Structured Content. An other example of widget is Calendar Widget that allows the redactors to select a date in a calendar.

Create a Custom Widget consists of three steps:

  1. Create a Java class inside your custom modules
  2. Add the new widget in the configuration file opencms-vfs.xml
  3. Use the widget within the Structured Content

Step 1: Extends an existing Java Class available from the API of OpenCMS


The developer should extend functionality of an existing widget. In this example I have extended the class CmsCalendarWidge because I want to inherit behaviour and a part of the HTML code of the existing widget.

package custom.simple.widget;

....

public class CmsCalendarCustomWidget extends CmsCalendarWidget {
 
   
 public CmsCalendarCustomWidget() {
  super();
 }
 

 public CmsCalendarCustomWidget(String configuration) {
  super(configuration);
 }

 
 @Override
 public I_CmsWidget newInstance() {
  return new CmsCalendarCustomWidget(getConfiguration());
 }

 
 
 @Override
 public String getDialogWidget(CmsObject cms, I_CmsWidgetDialog widgetDialog, I_CmsWidgetParameter param) {
  
  StringBuffer result = new StringBuffer();
   result.append("");

   /*  In this method,  developer can put code to implement  specific functions of the widget.
the developer can write HTML to realize graphic components
   */ 
 
  result.append("
"); return result.toString(); } }

Step 2: Modify opencms-vfs.xml


OpenCMS uses many files of configuration as opencms-vfs.xml. This file is located at the path /WEB-INF/config/opencms-vfs.xml. The developer has to insert the class that implements the new widget and give it an alias in order to reuse the alias in the definition of the Structured Content.
<xmlcontent>
      <widgets>
        ...
        <widget class="custom.simple.widget.CmsCalendarCustomWidget" alias="MyWidget"/>
        ...
      </widgets>
      <schematypes>
          ...
      </schematypes>
</xmlcontent>

Step 3: Use new Widget in the Structured Content


The developer can use the alias given to the widget in the previous step and associate it with an Element defined in the structured content. As we can see the right position to give this inform ation is the <xsd:annotation> tag
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">

 <xsd:include schemaLocation="opencms://opencms-xmlcontent.xsd"/>
 
 <xsd:element name="Videoleziones" type="OpenCmsSimpleStructuredContents"/>
 
 <xsd:complexType name="OpenCmsSimpleStructuredContents">
  <xsd:sequence>
   <xsd:element name="SimpleStructuredContent" type="OpenCmsSimpleStructuredContent" minOccurs="0" maxOccurs="unbounded"/>
  </xsd:sequence>
 </xsd:complexType>

 <xsd:complexType name="OpenCmsSimpleStructuredContent">
  <xsd:sequence>
   <xsd:element name="Titolo" type="OpenCmsString" />
   <xsd:element name="Data" type="OpenCmsDateTime" />
  </xsd:sequence>
 </xsd:complexType>
 <xsd:annotation>
  <xsd:appinfo>
   <layouts>
    <layout element="Titolo" widget="StringWidget" />
    <layout element="Data" widget="MyWidget" />
   </layouts>
  </xsd:appinfo>
 </xsd:annotation>  
</xsd:schema>
I hope this mini guide could help developers to know the elements he needs to write a custom widget in OpenCMS.

Suggested Pages