Article summary

Summary

Discusses how to use Apache CXF to create Java proxy classes that consume a third-party web service. The Java proxy classes are used to create an AEM Service that is deployed to Adobe Experience Manager. In addition, discusses how to invoke an OSGi bundle operation from the client web page using sling.GetService().

Based on community feedback, this article was modified to include the web service Java files in a Maven Archetype project as opposed to using an Eclipse Plug-in project to create the OSGi bundle. 

For information about using JAX-WS to create the Java proxy files, see Creating Experience Manager bundles that consume web services.  

For information about using Web Services and AEM 6 Touch UI component, see Creating Adobe Experience Manager Touch UI components that consume web services.

This article discusses using a WSDL to consume a web service. To learn how to build an AEM application that consumes a Restful web service, see Creating Adobe Experience Manager services that invoke third party Restful web services.

Digital Marketing Solution(s) Adobe Experience Manager (Adobe CQ)
Audience
Developer (intermediate)
Required Skills
Java, web services, XML
Tested On Adobe Experience Manager 5.6, 6.x

Note:

This workflow works on Adobe CQ; however, you may encounter the following exception:

Caused by: java.lang.ClassNotFoundException: com.sun.xml.internal.ws.spi.ProviderImpl
at org.apache.sling.commons.classloader.impl.ClassLoaderFacade.loadClass(ClassLoaderFacade.java:127)
at java.lang.ClassLoader.loadClass(Unknown Source)
at javax.xml.ws.spi.FactoryFinder.safeLoadClass(Unknown Source)
... 107 more
Solution:
To fix this issue and ensure that you can create a bundle that consumes web services as described in this article, modify the sling.properties file located in the crx-quickstart\conf folder. Add the following line of code to this file: sling.bootdelegation.com.sun=com.sun.*. Then restart the server using the JCR file. Once you perform this task, you can follow along with this article.

If you start CQ using the start script, CQ creates a new sling.properties file directly under crx-quickstart folder. If you start the server again using "start" script, it picks the newly created sling.properties file, not the original one(under crx-quickstart\conf folder). Make sure you modify the one under the crx-quickstart folder if you are using the start script as opposed to the JAR file. 

* GeoIP_WebService-1.0.zip
AEM 6/6.1/6.2 package. To view this sample page, use this URL: http://localhost:4502/content/GeoWebServicePage.html
* geo_webservice-1.0.zip
Here is an AEM 5.6 package that accompanies this development article. To run this application, ensure that you configure the sling.properties file. Then deploy using package manager. To view the page that displays data returned from the web service, use this URL: http://localhost:4502/content/geoExample.html.

Note:

This example invokes a third party service from AEM. Before following along with this example, you can test the third party service to ensure it works by going to this URL: http://www.webservicex.net/New/Home/ServiceDetail/64.

Introduction

You can create an Adobe Experience Manager (AEM) OSGi bundle that consumes data from a third-party web service (a SOAP web service) and displays the data in a web page. For example, assume that you want an AEM page to display results of an operation that looks up countries by IP address. In this situation, you can create an AEM OSGi bundle that retrieves data from a third-party web service and displays the data within a web page.

The following illustration shows data being retrieved from a third-party web service and displayed in a web page.

WebServiceGeo

You can develop an OSGi bundle that contains Java proxy classes that were created by using Apache CFX. That is, you can use a tool such as Apache CXF WSDL to Java to generate the Java proxy classes that are based on the WSDL of an external web service. For information about Apache CXF, see WSDL to Java.

Then you can use these Java proxy classes within your OSGi bundle. The OSGi bundle that is created in this development article contains Java proxy classes that consume operations exposed by the following WSDL:

http://www.webservicex.net/geoipservice.asmx?wsdl

The web service operation in this article returns the country in which the IP address is located.  

<GeoIP xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.webservicex.net/">
<ReturnCode>1</ReturnCode>
<IP>72.14.228.129</IP>
<ReturnCodeDetails>Success</ReturnCodeDetails>
<CountryName>United States</CountryName>
<CountryCode>USA</CountryCode>
</GeoIP>

An OSGi bundle lets you dynamically load, unload, configure, and control the Java module without restarting the server. The tool that is used in this development article to create the OSGi bundle is Eclipse. All of the instructions needed to build an OSGi bundle that contains Java web service proxy classes are covered in this development article. The following illustrations shows the relationship between the Java proxy classes and the Java class that uses @Service and @Component annotations. 

ProjectFiles
Java proxy classes that consume a third-party web service

Note:

Before following along with this development article, make sure that you have Eclipse 3.6.1 or higher. Eclipse is used to create the OSGi bundle that contains the Java proxy classes.

Create an AEM application folder structure

You can create an Experience Manager application folder structure that contains templates, components, and pages. Create an application folder structure that displays data from a third-party web service. Before you create application assets such as templates, components, or pages, you create an application, which is essentially a specific folder. You can create this folder structure by using CRXDE Lite.

CQAppSetup

The following describes each application folder:

  • application name: contains all of the resources that an application uses. The resources can be templates, pages, components, and so on
  • components: contains components that your application uses
  • page: contains page components. A page component is a script such as a JSP file
  • global: contains global components that your application uses
  • template: contains templates that you can base page components on
  • src: contains source code that comprises an OSGi component (this development does not create an OSGi bundle using this folder or CRXDE. Rather Eclipse is used)
  • install: contains a compiled OSGi bundles container

To create an application folder structure, perform these steps:

  1. To view the CQ welcome page, enter the URL http://[host name]:[port] into a web browser. For example, http://localhost:4502.

  2. Select CRXDE Lite.

  3. Right-click the apps folder (or the parent folder), select Create, Create Folder.

  4. Enter the folder name into the Create Folder dialog box. Enter geowebservice.

  5. Repeat steps 1-4 for each folder specified in the previous illustration.

  6. Click the Save All button.

Note:

You have to click the Save All button when working in CRXDE Lite for the changes to be made.

Create a template

You can create a template by using CRXDE Lite. A CQ template enables you to define a consistent style for the pages in your application. A template comprises of nodes that specify the page structure. For more information about templates, see Templates.

To create a CQ template, perform these steps:

  1. To view the CQ welcome page, enter the URL http://[host name]:[port] into a web browser. For example, http://localhost:4502.

  2. Select CRXDE Lite.

  3. Right-click the template folder (within your application), select Create, Create
    Template.

  4. Enter the following information into the Create Template dialog box:

    •  Label: The name of the template to create. Enter geoTemplate.
    • Title: The title that is assigned to the template
    • Description: The description that is assigned to the template
    • Resource Type: The component's path that is assigned to the template and copied to implementing pages. Enter geowebservice/components/page/geoTemplate.
    • Ranking: The order (ascending) in which this template will appear in relation to other templates. Setting this value to 1 ensures that the template appears first in the list.
  5. Add a path to Allowed Paths. Click on the plus sign and enter the following value: /content(/.*)?.

  6. Click Next for Allowed Parents.

  7. Select OK on Allowed Children.

Create a render component that uses the template

Components are re-usable modules that implement specific application logic to render the content of your web site. You can think of a component as a collection of scripts (for example, JSPs, Java servlets, and so on) that completely realize a specific function. In order to realize this functionality, it is your responsibility as a CQ developer to create scripts that perform specific functionality. For more information about components, see Components.

By default, a component has at least one default script, identical to the name of the component.
To create a render component:

  1. To view the CQ welcome page, enter the URL http://[host name]:[port] into a web browser. For example, http://localhost:4502.

  2. Select CRXDE Lite.

  3. Right-click /apps/geowebservice/components/page, then select
    Create, Create Component.

  4. Enter the following information into the Create Component dialog box:

    • Label: The name of the component to create. Enter geoTemplate.
    • Title: The title that is assigned to the component
    • Description: The description that is assigned to the template
    • Super Type: foundation/components/page (in AEM 6, you specify this value for page components. In previous versions of AEM, this was not required.)
  5. Select Next for Advanced Component Settings and Allowed Parents.

  6. Select OK on Allowed Children.

  7. Open the geoTemplate.jsp located at: /apps/geowebservice/components/page/geoTemplate/geoTemplate.jsp.

  8. Enter the following HTML code:

<html>
<head>
<title>Hello World !!!</title>
</head>
<body>
<h1>Hello Web Services</h1>
<h2>This page will contain data from a third-party web service</h2>
</body>
</html>

Create Java proxy classes using Apache CXF that consume the soap stack of the external web service

You can use Apache CXF to convert a third-party WSDL to Java proxy classes. These Java classes enable you to invoke operations exposed by the soap stack. 

To create Java proxy classes using Apache CXF, perform these steps:

  1. Download Apache CFX on the client computer. (See http://cxf.apache.org/download.html.)

  2. Install JDK 1.6 or later.

    • Add the JDK bin directory to your class path.
    • Add the JRE bin directory to your class path. This bin is located in the [JDK_INSTALL_LOCATION]/jre directory.
    • Set the JAVA_HOME environment variable to the directory where you installed the JDK. The JDK 1.6 includes the wsimport program used in the build.xml file. JDK 1.5 does not include that program.
  3. Open the command line and change the directory to the apache-cxf-2.6.0\bin. This directory contains the wsdl2java BAT file that you use.

  4. Enter the following command:

wsdl2java -p com.aem.ws -d c:\APIs http://www.webservicex.net/geoipservice.asmx?wsdl

The -p argument specifies the package in which the Java proxy classes are placed into. The -d argument specifies the directory in which the Java proxy classes are placed into. Finally the URL of the WSDL is specified.   These Java proxy classes are imported into a Maven Archetype project used to create the custom AEM service. 

The following illustration shows the Java proxy files that Apache CXF creates.

JavaFiles

Setup Maven in your development environment

You can use Maven to build an OSGi bundle that contains a Sling Servlet. Maven manages required JAR files that a Java project needs in its class path. Instead of searching the Internet trying to find and download third-party JAR files to include in your project’s class path, Maven manages these dependencies for you.

You can download Maven 3 from the following URL:

http://maven.apache.org/download.html

After you download and extract Maven, create an environment variable named M3_HOME. Assign the Maven install location to this environment variable. For example:

C:\Programs\Apache\apache-maven-3.0.4

Set up a system environment variable to reference Maven. To test whether you properly setup Maven, enter the following Maven command into a command prompt:

%M3_HOME%\bin\mvn -version

This command provides Maven and Java install details and resembles the following message:

Default locale: en_US, platform encoding: Cp1252
OS name: "windows 7", version: "6.1", arch: "amd64", family: "windows"

Note: It is recommended that you use Maven 3.0.3 or greater. For more information about setting up Maven and the Home variable, see: Maven in 5 Minutes.

Next, copy the Maven configuration file named settings.xml from [install location]\apache-maven-3.0.4\conf\ to your user profile. For example, C:\Users\scottm\.m2\.

You have to configure your settings.xml file to use Adobe’s public repository. For information, see Adobe Public Maven Repository at http://repo.adobe.com/.

The following XML code represents a settings.xml file that you can use.

<?xml version="1.0" encoding="UTF-8"?>
 
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at
 
    http://www.apache.org/licenses/LICENSE-2.0
 
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
-->
 
<!--
 | This is the configuration file for Maven. It can be specified at two levels:
 |
 |  1. User Level. This settings.xml file provides configuration for a single user, 
 |                 and is normally provided in ${user.home}/.m2/settings.xml.
 |
 |                 NOTE: This location can be overridden with the CLI option:
 |
 |                 -s /path/to/user/settings.xml
 |
 |  2. Global Level. This settings.xml file provides configuration for all Maven
 |                 users on a machine (assuming they're all using the same Maven
 |                 installation). It's normally provided in 
 |                 ${maven.home}/conf/settings.xml.
 |
 |                 NOTE: This location can be overridden with the CLI option:
 |
 |                 -gs /path/to/global/settings.xml
 |
 | The sections in this sample file are intended to give you a running start at
 | getting the most out of your Maven installation. Where appropriate, the default
 | values (values used when the setting is not specified) are provided.
 |
 |-->
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
  <!-- localRepository
   | The path to the local repository maven will use to store artifacts.
   |
   | Default: ~/.m2/repository
  <localRepository>/path/to/local/repo</localRepository>
  -->
 
  <!-- interactiveMode
   | This will determine whether maven prompts you when it needs input. If set to false,
   | maven will use a sensible default value, perhaps based on some other setting, for
   | the parameter in question.
   |
   | Default: true
  <interactiveMode>true</interactiveMode>
  -->
 
  <!-- offline
   | Determines whether maven should attempt to connect to the network when executing a build.
   | This will have an effect on artifact downloads, artifact deployment, and others.
   |
   | Default: false
  <offline>false</offline>
  -->
 
  <!-- pluginGroups
   | This is a list of additional group identifiers that will be searched when resolving plugins by their prefix, i.e.
   | when invoking a command line like "mvn prefix:goal". Maven will automatically add the group identifiers
   | "org.apache.maven.plugins" and "org.codehaus.mojo" if these are not already contained in the list.
   |-->
  <pluginGroups>
    <!-- pluginGroup
     | Specifies a further group identifier to use for plugin lookup.
    <pluginGroup>com.your.plugins</pluginGroup>
    -->
  </pluginGroups>
 
  <!-- proxies
   | This is a list of proxies which can be used on this machine to connect to the network.
   | Unless otherwise specified (by system property or command-line switch), the first proxy
   | specification in this list marked as active will be used.
   |-->
  <proxies>
    <!-- proxy
     | Specification for one proxy, to be used in connecting to the network.
     |
    <proxy>
      <id>optional</id>
      <active>true</active>
      <protocol>http</protocol>
      <username>proxyuser</username>
      <password>proxypass</password>
      <host>proxy.host.net</host>
      <port>80</port>
      <nonProxyHosts>local.net|some.host.com</nonProxyHosts>
    </proxy>
    -->
  </proxies>
 
  <!-- servers
   | This is a list of authentication profiles, keyed by the server-id used within the system.
   | Authentication profiles can be used whenever maven must make a connection to a remote server.
   |-->
  <servers>
    <!-- server
     | Specifies the authentication information to use when connecting to a particular server, identified by
     | a unique name within the system (referred to by the 'id' attribute below).
     | 
     | NOTE: You should either specify username/password OR privateKey/passphrase, since these pairings are 
     |       used together.
     |
    <server>
      <id>deploymentRepo</id>
      <username>repouser</username>
      <password>repopwd</password>
    </server>
    -->
     
    <!-- Another sample, using keys to authenticate.
    <server>
      <id>siteServer</id>
      <privateKey>/path/to/private/key</privateKey>
      <passphrase>optional; leave empty if not used.</passphrase>
    </server>
    -->
  </servers>
 
  <!-- mirrors
   | This is a list of mirrors to be used in downloading artifacts from remote repositories.
   | 
   | It works like this: a POM may declare a repository to use in resolving certain artifacts.
   | However, this repository may have problems with heavy traffic at times, so people have mirrored
   | it to several places.
   |
   | That repository definition will have a unique id, so we can create a mirror reference for that
   | repository, to be used as an alternate download site. The mirror site will be the preferred 
   | server for that repository.
   |-->
  <mirrors>
    <!-- mirror
     | Specifies a repository mirror site to use instead of a given repository. The repository that
     | this mirror serves has an ID that matches the mirrorOf element of this mirror. IDs are used
     | for inheritance and direct lookup purposes, and must be unique across the set of mirrors.
     |
    <mirror>
      <id>mirrorId</id>
      <mirrorOf>repositoryId</mirrorOf>
      <name>Human Readable Name for this Mirror.</name>
      <url>http://my.repository.com/repo/path</url>
    </mirror>
     -->
  </mirrors>
   
  <!-- profiles
   | This is a list of profiles which can be activated in a variety of ways, and which can modify
   | the build process. Profiles provided in the settings.xml are intended to provide local machine-
   | specific paths and repository locations which allow the build to work in the local environment.
   |
   | For example, if you have an integration testing plugin - like cactus - that needs to know where
   | your Tomcat instance is installed, you can provide a variable here such that the variable is 
   | dereferenced during the build process to configure the cactus plugin.
   |
   | As noted above, profiles can be activated in a variety of ways. One way - the activeProfiles
   | section of this document (settings.xml) - will be discussed later. Another way essentially
   | relies on the detection of a system property, either matching a particular value for the property,
   | or merely testing its existence. Profiles can also be activated by JDK version prefix, where a 
   | value of '1.4' might activate a profile when the build is executed on a JDK version of '1.4.2_07'.
   | Finally, the list of active profiles can be specified directly from the command line.
   |
   | NOTE: For profiles defined in the settings.xml, you are restricted to specifying only artifact
   |       repositories, plugin repositories, and free-form properties to be used as configuration
   |       variables for plugins in the POM.
   |
   |-->
  <profiles>
    <!-- profile
     | Specifies a set of introductions to the build process, to be activated using one or more of the
     | mechanisms described above. For inheritance purposes, and to activate profiles via <activatedProfiles/>
     | or the command line, profiles have to have an ID that is unique.
     |
     | An encouraged best practice for profile identification is to use a consistent naming convention
     | for profiles, such as 'env-dev', 'env-test', 'env-production', 'user-jdcasey', 'user-brett', etc.
     | This will make it more intuitive to understand what the set of introduced profiles is attempting
     | to accomplish, particularly when you only have a list of profile id's for debug.
     |
     | This profile example uses the JDK version to trigger activation, and provides a JDK-specific repo.
    <profile>
      <id>jdk-1.4</id>
 
      <activation>
        <jdk>1.4</jdk>
      </activation>
 
      <repositories>
        <repository>
          <id>jdk14</id>
          <name>Repository for JDK 1.4 builds</name>
          <url>http://www.myhost.com/maven/jdk14</url>
          <layout>default</layout>
          <snapshotPolicy>always</snapshotPolicy>
        </repository>
      </repositories>
    </profile>
    -->
 
    <!--
     | Here is another profile, activated by the system property 'target-env' with a value of 'dev',
     | which provides a specific path to the Tomcat instance. To use this, your plugin configuration
     | might hypothetically look like:
     |
     | ...
     | <plugin>
     |   <groupId>org.myco.myplugins</groupId>
     |   <artifactId>myplugin</artifactId>
     |   
     |   <configuration>
     |     <tomcatLocation>${tomcatPath}</tomcatLocation>
     |   </configuration>
     | </plugin>
     | ...
     |
     | NOTE: If you just wanted to inject this configuration whenever someone set 'target-env' to
     |       anything, you could just leave off the <value/> inside the activation-property.
     |
    <profile>
      <id>env-dev</id>
 
      <activation>
        <property>
          <name>target-env</name>
          <value>dev</value>
        </property>
      </activation>
 
      <properties>
        <tomcatPath>/path/to/tomcat/instance</tomcatPath>
      </properties>
    </profile>
    -->
   
 
<profile>
 
                <id>adobe-public</id>
 
                <activation>
 
                    <activeByDefault>true</activeByDefault>
 
                </activation>
 
                <repositories>
 
                  <repository>
 
                    <id>adobe</id>
 
                    <name>Nexus Proxy Repository</name>
 
                    <url>http://repo.adobe.com/nexus/content/groups/public/</url>
 
                    <layout>default</layout>
 
                  </repository>
 
                </repositories>
 
                <pluginRepositories>
 
                  <pluginRepository>
 
                    <id>adobe</id>
 
                    <name>Nexus Proxy Repository</name>
 
                    <url>http://repo.adobe.com/nexus/content/groups/public/</url>
 
                    <layout>default</layout>
 
                  </pluginRepository>
 
                </pluginRepositories>
 
            </profile>
 
</profiles>
 
  <!-- activeProfiles
   | List of profiles that are active for all builds.
   |
  <activeProfiles>
    <activeProfile>alwaysActiveProfile</activeProfile>
    <activeProfile>anotherAlwaysActiveProfile</activeProfile>
  </activeProfiles>
  -->
</settings>

Note:

. The Adobe repository URL is now made secured. Change http://repo.adobe.com/nexus/content/groups/public/ to https://repo.adobe.com/nexus/content/groups/public/.

The Adobe repository URL is now made secured. Changehttp://repo.adobe.com/nexus/content/groups/public/to https://repo.adobe.com/nexus/content/groups/public/.
The Adobe repository URL is now made secured. Changehttp://repo.adobe.com/nexus/content/groups/public/to https://repo.adobe.com/nexus/content/groups/public/.

Create an Experience Manager archetype project 

You can create an Experience Manager archetype project by using the Maven archetype plugin. In this example, assume that the working directory is C:\AdobeCQ. 

maven
Maven generated files

To create an Experience Manager archetype project, perform these steps:

  1. Open the command prompt and go to your working directory (for example, C:\AdobeCQ).

  2. Run the following Maven command:

    mvn archetype:generate -DarchetypeRepository=https://repo.adobe.com/nexus/content/groups/public/ -DarchetypeGroupId=com.day.jcr.vault -DarchetypeArtifactId=multimodule-content-package-archetype -DarchetypeVersion=1.0.2 -DgroupId=foo.service.aem.webservice -DartifactId=webservice -Dversion=1.0-SNAPSHOT -Dpackage=foo.service.aem.webservice -DappsFolderName=myproject -DartifactName="My Project" -DcqVersion="5.6.1" -DpackageGroup="My Company"

  3. When prompted, Specify Y

  4. Once done, you will see a message like:

    [[INFO] Total time: 14:46.131s
    [INFO] Finished at: Wed Mar 27 13:38:58 EDT 2013
    [INFO] Final Memory: 10M/184M

  5. Change the command prompt to the generated project. For example: C:\AdobeCQ\webservice. Run the following Maven command:

    mvn eclipse:eclipse

    After you run this command, you can import the project into Eclipse as discussed in the next section.

Add Java files to the Maven project using Eclipse 

To make it easier to work with the Maven generated project, import it into the Eclipse development environment, as shown in the following illustration.

project
An Eclipse Import dialog

The Java files required to build an OSGi bundle that consumes a third-party web service are placed into different Java packages. Delete all files and packages other than these ones:

  • foo.service.aem.webservice 
  • foo.service.aem.webserviceImpl

Keep only the HelloService and HelloServiceImpl Java files. 

Next create a Java package named com.aem.ws. Import all of the Java proxy classes that were created by using Apache CFX.  Once done, the com.aem.ws package looks like this illustration. 

proxy
Proxy classes imported into the Maven Archetype project

HelloService interface

THe HelloService interface defines the method exposed by the AEM service. 

package foo.service.aem.webservice;

/**
 * A simple service interface
 */
public interface HelloService {
    
    /**
     * @return the name country in which IP is located
     */
	public String getCountryBasedonIP(String ipAddress) ; 
}

HelloServiceImpl class

The HelloServiceImpl class defines application logic for the getCountryBasedonIP method.  This method creates Java object based on the Java proxy web service classes. The IP value that is passed to this method is used in the web service call. The country in which the IP value is located is returned by getCountryBasedonIP

The following Java code represents  HelloServiceImpl.

package foo.service.aem.webservice.impl;



import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.jcr.api.SlingRepository;
import com.aem.ws.* ; //import the web servce classes

import foo.service.aem.webservice.HelloService;

/**
 * One implementation of the {@link HelloService}. Note that
 * the repository is injected, not retrieved.
 */
@Service
@Component(metatype = false)
public class HelloServiceImpl implements HelloService {
    

public String getCountryBasedonIP(String ipAddress) {
    	
    	try
    	{
    		
    		//Create Objects based on WEB Service
    		com.aem.ws.GeoIPService global = new com.aem.ws.GeoIPService(); 
    		   
    		com.aem.ws.GeoIPServiceSoap geoIPSOAP = global.getGeoIPServiceSoap12();
    		 
    		com.aem.ws.GeoIP ip = geoIPSOAP.getGeoIPContext();
    		                 
    		ip.setIP(ipAddress) ; 
    		
    		return ip.getCountryName() ; 
    		
    	}
    	catch(Exception e)
    	{
    		e.printStackTrace();
    	}
    	return ""; 
    }
}

Modify the Maven POM file

Modify the POM files to successfully build the OSGi bundle. In the POM file located at C:\AdobeCQ\key, add the following dependencies.

  • org.apache.felix.scr
  • org.apache.felix.scr.annotations
  • javax.xml.bind.annotation

The following code represents the POM file located at C:\AdobeCQ\webservice.

<?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/maven-v4_0_0.xsd ">
    <modelVersion>4.0.0</modelVersion>
    <!-- ====================================================================== -->
    <!-- P A R E N T P R O J E C T D E S C R I P T I O N -->
    <!-- ====================================================================== -->
    <parent>
        <groupId>foo.service.aem.webservice</groupId>
        <artifactId>webservice</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <!-- ====================================================================== -->
    <!-- P R O J E C T D E S C R I P T I O N -->
    <!-- ====================================================================== -->

    <artifactId>webservice-bundle</artifactId>
    <packaging>bundle</packaging>
    <name>My Project Bundle</name>

    <dependencies>
       
       
       <dependency>
	<groupId>javax.xml.soap</groupId>
	<artifactId>javax.xml.soap-api</artifactId>
	<version>1.3.7</version>
</dependency>
       
       
            
       
       <dependency>
	<groupId>org.apache.sling</groupId>
	<artifactId>org.apache.sling.jcr.api</artifactId>
	<version>2.3.0</version>
</dependency>
       
       
       <dependency>
	<groupId>javax.xml.bind</groupId>
	<artifactId>jaxb-api</artifactId>
	<version>2.1</version>
</dependency>
       
       
       
       
        <dependency>
            <groupId>org.osgi</groupId>
            <artifactId>org.osgi.compendium</artifactId>
        </dependency>
        <dependency>
            <groupId>org.osgi</groupId>
            <artifactId>org.osgi.core</artifactId>
        </dependency>
                  
        <dependency>
            <groupId>org.apache.felix</groupId>
            <artifactId>org.apache.felix.scr.annotations</artifactId>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
              
            <dependency> 
            <groupId>com.adobe.granite</groupId> 
            <artifactId>com.adobe.granite.fragment.xml</artifactId>
            <version>0.1.0</version> 
            <scope>provided</scope> 
        </dependency>
          
        <dependency>
    <groupId>javax.mail</groupId>
    <artifactId>javax.mail-api</artifactId>
    <version>1.5.2</version>
</dependency>
          
         
    </dependencies>

    <!-- ====================================================================== -->
    <!-- B U I L D D E F I N I T I O N -->
    <!-- ====================================================================== -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-scr-plugin</artifactId>
                <executions>
                    <execution>
                        <id>generate-scr-descriptor</id>
                        <goals>
                            <goal>scr</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <extensions>true</extensions>
                <configuration>
                    <instructions>
                        <Bundle-SymbolicName>foo.service.aem.webservice.webservice-bundle</Bundle-SymbolicName>
                    </instructions>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.sling</groupId>
                <artifactId>maven-sling-plugin</artifactId>
                <configuration>
                    <slingUrl>http://${crx.host}:${crx.port}/apps/myproject/install</slingUrl>
                    <usePut>true</usePut>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-javadoc-plugin</artifactId>
                 <configuration>
                    <excludePackageNames>
                        *.impl
                    </excludePackageNames>
                 </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Build the OSGi bundle using Maven

To build the OSGi bundle by using Maven, perform these steps:

  1. Open the command prompt and go to the C:\AdobeCQ\webservice folder.

  2. Run the following maven command: mvn -PautoInstallPackage install.

  3. The OSGi component can be found in the following folder: C:\AdobeCQ\webservice\core\target. The file name of the OSGi component is webservice-bundle-1.0-SNAPSHOT.jar.

Note:

The command -PautoInstallPackage automatically deploys the OSGi bundle to AEM.

Modify the geoTemplate JSP to call the methods specified in the OSGi bundle

After you build the OSGi bundle and confirm that it has been deployed, you can call its methods from a JSP that is part of a page component. In this development article, the geoTemplate.jsp invokes the getCountryBasedonIP method that calls operations exposed by the WSDL. Modify this JSP so that it resembles the following JSP code.

<%@include file="/libs/foundation/global.jsp"%>
<h1><%= properties.get("title", currentPage.getTitle()) %></h1>
  
<h2>Here is geo ip information based on this IP address  72.14.228.129:</h2>
<%
   
foo.service.aem.webservice.HelloService ipService = sling.getService(foo.service.aem.webservice.HelloService.class);
String country = ipService.getCountryBasedonIP("72.14.228.129") ; 


%>
  
<h2>This page invokes the AEM web service</h2>
<h3>The country is: <%=country%></h3>

Notice how a com.aem.ws.GeoIPService object can be created and its methods are called. When a method, such as ip.getCountryName is invoked, an operation exposed by the WSDL is called. The data returned by the web service is displayed in the JSP.

Create a page that displays data retrieved from the OSGi bundle

The final task that you perform in order to see a web page that displays data retrieved from an OSGi bundle is to create a site that contains a page that is based on the geoTemplate (the template created earlier in this development article).

The following illustration shows the data returned by the OSGi bundle being displayed in the web page. 

clientPage

To create a web page that displays data retrieved from an OSGi bundle, perform these tasks:

  1. Go to http://localhost:4502/siteadmin#/content. 

  2. Select New, New Page.

  3. Specify the title of the page in the Title field.

  4. Specify the name of the page in the Name field.

  5. Select geoTemplate from the template list that appears. This value represents the template that is created in this development article. If you do not see it, then repeat the steps in this development article. For example, if you made a typing mistake when entering in path information when creating the template, the template will not show up in the New Page dialog box.

  6. Open the new page that you created by double-clicking it in the right pane. The new page opens in a web browser. You should see a page displaying data similar to the previous illustration.

See also

Congratulations, you have just created an AEM application that consumes web services. Please refer to the AEM community page for other articles that discuss how to build AEM services/applications.

This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License  Twitter™ and Facebook posts are not covered under the terms of Creative Commons.

Legal Notices   |   Online Privacy Policy