com.atlassian.confluence.content.render.xhtml.migration.exceptions.UnknownMacroMigrationException: The macro 'next_previous_links' is unknown.

Step 2: Developing the Carbon Components

Before you begin, be sure to setup your project as explained in the previous topic. If you have done that, you can now proceed to the second step in developing the Student Management feature, which is to develop the required components:

Follow the instructions given bellow.


Creating the server component

The instructions in this section will explain how to develop the server component of the Student Management feature. Before you begin, ensure that the development project is created. The server component is only one of the components that constitute the Student Management feature. See the sections on creating the service stub and creating the UI component for instructions on how to create the remaining components.

Creating the sub Maven project for the server component

Follow the steps given below.

  1. Go to the student-manager-components Maven project, which you defined previously.
  2. Create a sub project called org.wso2.carbon.student.mgt with the following details:
    • artifactId - org.wso2.carbon.student.mgt
    • packaging - bundle
    • name - WSO2 Carbon - Student Manager Server Component
    • plugin - maven-bundle-plugin

This will be an OSGI bundle. So, we have to configure the Apache Felix plugin to set up the configurations.

Updating the pom.xml files

There are two pom.xml files to update. First, you must update the pom.xml at the server component level. Then, you can update the pom.xml file at the root component level:

  • Update the org.wso2.carbon.student.mgt → pom.xml file:

     Click here to see the updated pom.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>student-manager-components</artifactId>
            <groupId>org.wso2.carbon</groupId>
            <version>4.2.0</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
     
        <artifactId>org.wso2.carbon.student.mgt</artifactId>
     
        <packaging>bundle</packaging>
        <name>WSO2 Carbon - Student Manager Server Component</name>
     
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.felix</groupId>
                    <artifactId>maven-bundle-plugin</artifactId>
                    <extensions>true</extensions>
                    <configuration>
                        <instructions>
                            <Bundle-SymbolicName>${pom.artifactId}</Bundle-SymbolicName>
                            <Bundle-Name>${pom.artifactId}</Bundle-Name>
                            <Export-Package>org.wso2.carbon.student.mgt.*</Export-Package>
                        </instructions>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </project>

    When you export packages for the OSGI bundle, remember that if you are using any API classes or any other dependencies in a separate package, you have to export them as well. In this example, we will have our data classes in the org.wso2.carbon.student.mgt.data package. Exporting the parent mgt package will export everything that is required..

  • Update the student-manager-components → pom.xml file:

     Click here to see the updated pom.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>student-manager</artifactId>
            <groupId>org.wso2.carbon</groupId>
            <version>4.2.0</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
     
        <artifactId>student-manager-components</artifactId>
     
        <packaging>pom</packaging>
        <name>WSO2 Carbon - Student Manager Components</name>
     
        <modules>
            <module>org.wso2.carbon.student.mgt</module>
            <!-- There are 2 more projects to be added here later in this tutorial stub, ui -->
        </modules>
    </project>

Adding Java classes to the server component

Now, create two java classes named Student (in src/main/java/org/wso2/carbon/student/mgt/data/) and StudentManager (in src/main/java/org/wso2/carbon/student/mgt/) in the org.wso2.carbon.student.mgt project. 

The Student class will simply hold a few student details (ID, first name, last name) with getters and setters as follows:

 Click here to see the sample Student class
package org.wso2.carbon.student.mgt.data;
 
public class Student {
    private int ID;
    private String firstName;
    private String lastName;
 
    public Student(int ID, String firstName, String lastName) {
        this.ID = ID;
        this.firstName = firstName;
        this.lastName = lastName;
    }
 
    public int getID() {
        return ID;
    }
    public void setID(int ID) {
        this.ID = ID;
    }
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}

The StudentManager class will create an array of students in the constructor and have a public method to return the array as follows:

 Click here to see a sample StudentManager class
package org.wso2.carbon.student.mgt;
 
import org.wso2.carbon.student.mgt.data.Student;
 
public class StudentManager {
    private Student[] students;
 
    public StudentManager() {
        students = new Student[2];
        students[0] = new Student(1234,"Amal", "Gunatilake");
        students[1] = new Student(4321, "John", "Carter");
    }
 
    public Student[] getStudents() {
        return students;
    }
}

Creating the services.xml file

Finally, the services.xml file should be configured as shown below to expose the StudentManager service. We have exposed StudentManager as our ServiceClass

 Click here to see the sample services.xml file
<serviceGroup>
    <service name="StudentManager" scope="transportsession">
        <transports>
            <transport>https</transport>
        </transports>
        <parameter name="ServiceClass">org.wso2.carbon.student.mgt.StudentManager</parameter>
    </service>
 
    <parameter name="adminService" locked="true">true</parameter>
    <parameter name="hiddenService" locked="true">true</parameter>
    <parameter name="AuthorizationAction" locked="true">/permission/protected/manage</parameter>
</serviceGroup>
  • <transport>https</transport>: Makes the service secure.
  • parameter name="adminService" : makes the service an admin service.
  • parameter name="hiddenService" : makes the service hidden to public.
  • parameter name="AuthorizationAction" : makes the service authorized.

As shown above, we have now exposed StudentManager as our ServiceClass.

Now, we have completed the server component. Follow the instructions in the next step to develop the service stub.


Creating the service stub

We will now continue developing the Student Management feature by developing the service stub component.The service stub will carry out the communication between the back end and front end components of the feature.

Before you begin, note the following:

In order to create this stub, we need the wsdl exposed from the service we created for the server component. However, note that you will not be able to access the wsdl from the browser since we have secured the connection.

  1. Until we retrieve the wsdl, open the <PRODUCT_HOME>/repository/conf/carbon.xml file and change the <HideAdminServiceWSDLs> parameter from true to false.
  2. Now do a Maven build.  
  3. Copy the org.wso2.carbon.student.mgt-4.2.0.jar that is inside the target folder to the <PRODUCT_HOME>/repository/components/dropins folder in your Carbon server.
  4. Start the server and go to https://localhost:9443/services/StudentManager?wsdl
  5. Save the wsdl as StudentManager.wsdl for later use in the stub.
  6. Revert the <HideAdminServiceWSDLs> parameter to the default setting.

Now, start creating the service stub.

Creating the sub Maven project for the service stub

Follow the steps given below.

  1. Go to the student-manager-components Maven project, which you defined previously.
  2. Create the org.wso2.carbon.student.mgt.stub sub project with the following details:
    • artifactId - org.wso2.carbon.student.mgt.stub
    • packaging - bundle
    • name - WSO2 Carbon - Student Manager Stub
    • dependency - axis2
    • dependency - axiom
    • dependency - wsdl4j
    • plugin - maven-antrun-plugin
    • plugin - build-helper-maven-plugin
    • plugin - maven-bundle-plugin

By using wsdl2java along with maven-antrun-plugin, you can generate the Java classes from the existing WSDL document. Copy StudentManager.wsdl to the src/main/resources/ folder.

Updating the pom.xml

Update the org.wso2.carbon.student.mgt.stub → pom.xml file as show below.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>student-manager-components</artifactId>
        <groupId>org.wso2.carbon</groupId>
        <version>4.2.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
 
    <artifactId>org.wso2.carbon.student.mgt.stub</artifactId>
 
    <packaging>bundle</packaging>
    <name>WSO2 Carbon - Student Manager Stub</name>
 
    <dependencies>
        <dependency>
            <groupId>org.apache.axis2.wso2</groupId>
            <artifactId>axis2</artifactId>
            <version>1.6.1.wso2v10</version>
        </dependency>
        <dependency>
            <groupId>org.apache.ws.commons.axiom.wso2</groupId>
            <artifactId>axiom</artifactId>
            <version>1.2.11.wso2v4</version>
        </dependency>
        <dependency>
            <groupId>wsdl4j.wso2</groupId>
            <artifactId>wsdl4j</artifactId>
            <version>1.6.2.wso2v4</version>
        </dependency>
    </dependencies>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-antrun-plugin</artifactId>
                <version>1.1</version>
                <executions>
                    <execution>
                        <id>source-code-generation</id>
                        <phase>process-resources</phase>
                        <goals>
                            <goal>run</goal>
                        </goals>
                        <configuration>
                            <tasks>
                                <path id="wsdl2java.classpath">
                                    <pathelement location="${settings.localRepository}/org/apache/ws/commons/axiom/wso2/axiom/1.2.11.wso2v4/axiom-1.2.11.wso2v4.jar"/>
                                    <pathelement location="${settings.localRepository}/org/apache/axis2/wso2/axis2-client/1.6.1.wso2v10/axis2-client-1.6.1.wso2v10.jar" />
                                    <pathelement location="${settings.localRepository}/org/apache/axis2/wso2/axis2/1.6.1.wso2v10/axis2-1.6.1.wso2v10.jar" />
                                </path>
                                <java classname="org.apache.axis2.wsdl.WSDL2Java" fork="true">
                                    <classpath refid="wsdl2java.classpath" />
                                    <arg line="-uri src/main/resources/StudentManager.wsdl -u -uw
                                     -o target/generated-code -p org.wso2.carbon.student.mgt.stub"/>
                                </java>
                            </tasks>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
 
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>build-helper-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <id>add-source</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>add-source</goal>
                        </goals>
                        <configuration>
                            <sources>
                                <source>target/generated-code/src</source>
                            </sources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
 
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <extensions>true</extensions>
                <configuration>
                    <instructions>
                        <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
                        <Bundle-Name>${project.artifactId}</Bundle-Name>
                        <Private-Package>
                        </Private-Package>
                        <Export-Package>
                            org.wso2.carbon.student.mgt.*
                        </Export-Package>
                        <Import-Package>
                            !org.wso2.carbon.student.mgt.*
                        </Import-Package>
                        <DynamicImport-Package>*</DynamicImport-Package>
                    </instructions>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Note:

  • Axis2 dependency has been used as the SOAP stack.
  • The Apache Axiom library provides an XML Infoset compliant object model implementation, which supports building the object tree on-demand.
  • The wsdl4j dependency has been used to generate the Java classes from the existing WSDL document using the wsdl2java.
  • The wsdl2java.classpath has been configured in the maven-antrun-plugin with the 3 dependencies as path elements.
<path id="wsdl2java.classpath"> 
<pathelement location="${settings.localRepository}/org/apache/ws/commons/axiom/wso2/axiom/1.2.11.wso2v4/axiom-1.2.11.wso2v4.jar"/> 
<pathelement location="${settings.localRepository}/org/apache/axis2/wso2/axis2-client/1.6.1.wso2v10/axis2-client-1.6.1.wso2v10.jar" /> 
<pathelement location="${settings.localRepository}/org/apache/axis2/wso2/axis2/1.6.1.wso2v10/axis2-1.6.1.wso2v10.jar" /> 
</path>

Make sure those paths are set properly according to the local Maven repository.

<java classname="org.apache.axis2.wsdl.WSDL2Java" fork="true"> 
<classpath refid="wsdl2java.classpath" /> 
<arg line="-uri src/main/resources/StudentManager.wsdl -u -uw -o target/generated-code -p org.wso2.carbon.student.mgt.stub"/> 
</java>

We have passed the StudentManager.wsdl to the org.apache.axis2.wsdl.WSDL2Java class. This will generate the source code in target/generated-code inside the org.wso2.carbon.student.mgt.stub package. The build-helper-maven-plugin will add the generated source code to the final JAR bundle. 


Creating the UI component

We will now continue developing the Student Management feature by creating the UI component.This component will be used to access the feature from the management console.

Creating the sub Maven project for the UI component

Follow the steps given below.

  1. Go to the student-manager-components Maven project, which you defined previously.
  2. Create a sub maven project named org.wso2.carbon.student.mgt.ui inside the student-manager-components project.
    • artifactId - org.wso2.carbon.student.mgt.ui
    • packaging - bundle
    • name - WSO2 Carbon - Student Manager UI Component
    • dependency - org.wso2.carbon.student.mgt.stub
    • plugin - maven-bundle-plugin 

    When adding this project, the parent project should be updated accordingly with <modules> and the current project with the <parent> tag. If you are using an IDE, the updates will happen automatically.

Creating the pom.xml file

Update the org.wso2.carbon.student.mgt.ui → pom.xml file as shown below.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>student-manager-components</artifactId>
        <groupId>org.wso2.carbon</groupId>
        <version>4.2.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>org.wso2.carbon.student.mgt.ui</artifactId>
    <packaging>bundle</packaging>
    <name>WSO2 Carbon - Student Manager UI Component</name>
 
    <dependencies>
        <dependency>
            <groupId>org.wso2.carbon</groupId>
            <artifactId>org.wso2.carbon.student.mgt.stub</artifactId>
            <version>4.2.0</version>
        </dependency>
    </dependencies>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <extensions>true</extensions>
                <configuration>
                    <instructions>
                        <Bundle-SymbolicName>${pom.artifactId}</Bundle-SymbolicName>
                        <Bundle-Name>${project.artifactId}</Bundle-Name>
                        <Export-Package>
                            org.wso2.carbon.student.mgt.*
                        </Export-Package>
                        <Import-Package>
                            *;resolution:=optional
                        </Import-Package>
                        <Carbon-Component>UIBundle</Carbon-Component>
                    </instructions>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

In the UI component, we additionally mention that it is the <Carbon-Component>UIBundle</Carbon-Component> when configuring OSGI.

Adding Java classes to the UI 

Now you can add the StudentManagerClient java class in the src/main/java/org/wso2/carbon/student/mgt/ui/ folder of the org.wso2.carbon.student.mgt.ui project.

package org.wso2.carbon.student.mgt.ui;
 
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;
import org.apache.axis2.context.ConfigurationContext;
import org.wso2.carbon.student.mgt.data.xsd.Student;
import org.wso2.carbon.student.mgt.stub.StudentManagerStub;
 
import java.rmi.RemoteException;
 
public class StudentManagerClient {
    private StudentManagerStub stub;
 
    public StudentManagerClient(ConfigurationContext configCtx, String backendServerURL, String cookie) throws Exception{
        String serviceURL = backendServerURL + "StudentManager";
        stub = new StudentManagerStub(configCtx, serviceURL);
        ServiceClient client = stub._getServiceClient();
        Options options = client.getOptions();
        options.setManageSession(true);
        options.setProperty(org.apache.axis2.transport.http.HTTPConstants.COOKIE_STRING, cookie);
    }
 
    public Student[] getStudents() throws Exception{
        try{
            return stub.getStudents();
        }catch (RemoteException e) {
            String msg = "Cannot get the list of students"
                    + " . Backend service may be unavailable";
            throw new Exception(msg, e);
        }
    }
}

Creating the index.jsp page

  1. Go to the src/main/resources/web/student-mg folder.
  2. Add the following to the index.jsp file:

    <%@ page import="org.apache.axis2.context.ConfigurationContext" %>
    <%@ page import="org.wso2.carbon.CarbonConstants" %>
    <%@ page import="org.wso2.carbon.ui.CarbonUIUtil" %>
    <%@ page import="org.wso2.carbon.utils.ServerConstants" %>
    <%@ page import="org.wso2.carbon.ui.CarbonUIMessage" %>
    <%@ page import="org.wso2.carbon.student.mgt.ui.StudentManagerClient" %>
    <%@ page import="org.wso2.carbon.student.mgt.data.xsd.Student" %>
    <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
    <%@ taglib uri="http://wso2.org/projects/carbon/taglibs/carbontags.jar" prefix="carbon" %>
    <%
            String serverURL = CarbonUIUtil.getServerURL(config.getServletContext(), session);
            ConfigurationContext configContext =
                    (ConfigurationContext) config.getServletContext().getAttribute(CarbonConstants.CONFIGURATION_CONTEXT);
            String cookie = (String) session.getAttribute(ServerConstants.ADMIN_SERVICE_COOKIE);
     
            StudentManagerClient client;
            Student[] students;
     
            try {
                client = new StudentManagerClient(configContext, serverURL, cookie);
                students = client.getStudents();
            } catch (Exception e) {
                CarbonUIMessage.sendCarbonUIMessage(e.getMessage(), CarbonUIMessage.ERROR, request, e);
    %>
                <script type="text/javascript">
                       location.href = "../admin/error.jsp";
                </script>
    <%
                return;
        }
    %>
     
    <div id="middle">
        <h2>Student Management</h2>
     
        <div id="workArea">
            <table class="styledLeft" id="moduleTable">
                    <thead>
                    <tr>
                        <th width="20%">ID</th>
                        <th width="40%">First Name</th>
                        <th width="40%">Last Name</th>
                    </tr>
                    </thead>
                    <tbody>
               <%
                       for(Student student:students){
               %>
                       <tr>
                           <td><%=student.getID()%></td>
                        <td><%=student.getFirstName()%></td>
                        <td><%=student.getLastName()%></td>
                    </tr>
               <%
                       }
               %>
                    </tbody>
             </table>
        </div>
    </div>

    In order to create StudentManagerClient, we have created the 3 parameters requested using the Carbon core.

    String serverURL = CarbonUIUtil.getServerURL(config.getServletContext(), session); ConfigurationContext configContext = (ConfigurationContext) config.getServletContext().getAttribute(CarbonConstants.CONFIGURATION_CONTEXT); String cookie = (String) session.getAttribute(ServerConstants.ADMIN_SERVICE_COOKIE);

    When creating the content, the <div id="middle"> tag will set the UI content in the Carbon server page, which will load the student information retrieved from the back end.

Adding the UI feature to the Carbon navigation panel

Now we have to create the link in the Carbon server navigation panel to load the index.jsp page that we just created. In order to do this, we have to create a component.xml file in the src/main/resources/META-INF folder as shown below.

<component xmlns="http://products.wso2.org/carbon">
    <menus>
        <menu>
            <id>studentmgt_menu</id>
            <i18n-key>student.menu</i18n-key>
            <i18n-bundle>org.wso2.carbon.student.mgt.ui.i18n.Resources</i18n-bundle>
            <parent-menu>manage_menu</parent-menu>
            <link>../student-mgt/index.jsp</link>
            <region>region1</region>
            <order>50</order>
            <style-class>manage</style-class>
            <icon>../student-mgt/images/students.gif</icon>
            <require-permission>/permission/protected/manage</require-permission>
        </menu>
    </menus>
</component>

Note:

  • <id>studentmgt_menu</id>: The ID to the new link that points to the index.jsp file.
  • <i18n-key>student.menu</i18n-key>: This points to the link name, which is defined in the i18n bundle.
  • <i18n-bundle>org.wso2.carbon.student.mgt.ui.i18n.Resources</i18n-bundle>: This loads the i18n Resource.properties file. (We will be adding this in the next few steps).
  • <parent-menu>manage_menu</parent-menu>: Defines the parent menu for the new link.
  • <link>../student-mgt/index.jsp</link>: The relative path to the index.jsp file.
  • <region>region1</region>: Defines the region in which the link should be located.
  • <order>50</order>: Defines the link order.
  • <style-class>manage</style-class>: Load the CSS styles for the new link.
  • <icon>../student-mgt/images/students.gif</icon>: Defines a small icon to appear with the link.
  • <require-permission>/permission/protected/manage</require-permission>: Defines the authorization category.

Creating the Resources.properties file and adding images

  1. Create the Resources.properties file in the src/main/resources/org/wso2/carbon/student/mgt/ui/i18n folder:

    student.menu=Students

    When creating the directory structure for the Resource.properties file, make sure that your IDE creates the right directory structure. Note that some IDEs wrongly create only one directory with the name org.wso2.carbon.student.mgt.ui.i18n. Further, when configuring the path to the component.xml file, omit the .properties extension. 

  2. Copy a small 24x24 pixels icon image to src/main/resources/web/student-mgt/images folder.

Now we have created all three components required for the Student Management feature:

  • org.wso2.carbon.student.mgt - Server component OSGI bundle.
  • org.wso2.carbon.student.mgt.stub - Communication stub OSGI bundle.
  • org.wso2.carbon.student.mgt.ui - UI component OSGI bundle.

We can manually install those 3 OSGI bundles (JAR files) by adding them to the <PRODUCT_HOME>/repository/components/dropins folder. Then, start the Carbon server. The Students link will now appears on the left side navigation panel.

com.atlassian.confluence.content.render.xhtml.migration.exceptions.UnknownMacroMigrationException: The macro 'next_previous_links2' is unknown.