Microservice SDK for Java
Overview
This section describes how to develop and deploy microservices on top of Cumulocity using the Microservice SDK for Java.
To get started, check the Hello World example.
Info: You can develop Cumulocity with any IDE and any build tool that you prefer, but the examples focus on Maven and Eclipse.
After reviewing the "Hello world" you may continue with the section Developing Java clients.
Finally, here are some references for getting started with the basic technologies underlying the SDK:
- The client libraries use the Cumulocity REST interfaces as underlying communication protocol as described in the section on REST.
- All examples and libraries are open source, check https://bitbucket.org/m2m.
JavaDoc for the Java Microservice SDK can be found on our resources site.
General prerequisites
To use the Java SE client libraries, you need to have at least Version 6 of the Java Development Kit for your operating system. Some of the examples require Java 7. Java 8 is not supported and some features may not work correctly with Java 8. To verify the version of your Java Development Kit, type
$ javac -version
The output needs to show a version number later than "1.6.0_24" for the basic examples.
Hello microservice!
This section shows you how to create a microservice that can be run on cumulocity.com, using Cumulocity Microservice SDK.
Prerequisites
Create an account on cumulocity.com, for example by using a free trial. At this step you will be provided with a dedicated URL address.
Verify, that you have Maven 3 installed with Java (7+):
$ mvn -v
Apache Maven 3.1.1 (0728685237757ffbf44136acec0402957f723d9a; 2013-09-17 17:22:22+0200)
Maven home: /usr/local/Cellar/maven/3.1.1/libexec
Java version: 1.7.0_45, vendor: Oracle Corporation
Java home: /Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home/jre
Default locale: en_US, platform encoding: UTF-8
OS name: "mac os x", version: "10.9.4", arch: "x86_64", family: "mac"
Info: Maven can be downloaded from http://maven.apache.org.
Verify the docker installation:
Cumulocity hosts linux/amd64 docker containers and not Windows containers. The docker version must be >= 1.12.6
$ docker version
Client:
Version: 1.12.6
API version: 1.24
OS/Arch: linux/amd64
Server:
Version: 1.12.6
API version: 1.24
OS/Arch: linux/amd64
Developing the "Hello, world!" agent
To develop a very simple "Hello, world!" agent for Cumulocity, you need to
- create a Maven project,
- add a dependency to the Cumulocity Microservice SDK library to the Maven pom.xml,
- create a Java application,
- configure the microservice,
- configure the build,
- build and run the Java application.
Creating a Maven project
To create a plain Java project with Maven, run
$ mvn archetype:generate -DgroupId=c8y.example -DartifactId=hello-world-microservice -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
This will create a folder "hello-world-microservice" in the current directory with a skeleton structure for your project.
Adding the Java Microservice library
Edit the "pom.xml" in the "hello-world-microservice" folder. Add a repositories
and a pluginRepositories
element to point to the Cumulocity Maven repository, which stores the client libraries.
<repositories>
<repository>
<id>cumulocity</id>
<layout>default</layout>
<url>http://download.cumulocity.com/maven/repository</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>public</id>
<url>http://download.cumulocity.com/maven/repository</url>
</pluginRepository>
</pluginRepositories>
Add dependency
elements for the Java Microservice SDK library (microservice-autoconfigure
) to the dependencies
section.
<dependency>
<groupId>com.nsn.cumulocity.clients-java</groupId>
<artifactId>microservice-autoconfigure</artifactId>
<version>${c8y.version}</version>
</dependency>
Edit the version
elements to use the latest version of the client library. The version can be determined by checking the Announcements section of the Cumulocity Help Center. The full file after editing can be found here.
Creating a Java application
Edit the "App.java" file in the folder "hello-world-microservice/src/main/java/c8y/example" with the following content:
package c8y.example;
import com.cumulocity.microservice.autoconfigure.MicroserviceApplication;
import org.springframework.boot.SpringApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@MicroserviceApplication
@RestController
public class App{
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
@RequestMapping("hello")
public String greeting(@RequestParam(value = "who", defaultValue = "world") String who) {
return "hello " + who + "!";
}
}
@MicroserviceApplication - is a simple way to add required behavior for Cumulocity Microservice, including:
- security
- subscription
- health indicator
- context
- internal platform API
- spring boot application
@RequestMapping - opens an endpoint for greeting.
Configuring the microservice
Add an "application.properties" file to the "src/main/resources" directory with the following properties:
application.name=hello-world
server.port=80
Add a "cumulocity.json" file to the "src/main/configuration" directory with the following content:
{
"apiVersion":"1",
"version":"@project.version@",
"provider": {
"name":"Cumulocity GmbH"
},
"isolation":"MULTI_TENANT",
"requiredRoles": [
],
"roles":[
]
}
This file is required to deploy the microservice in the Cumulocity infrastructure.
Configuring the build
To create a deployable ZIP file, you need to add the following to your .pom file:
<properties>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<spring-boot-dependencies.version>1.5.7.RELEASE</spring-boot-dependencies.version>
<c8y.version>9.8.0</c8y.version>
</properties>
<dependencies>
<dependency>
<groupId>com.nsn.cumulocity.clients-java</groupId>
<artifactId>microservice-autoconfigure</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<!-- microservice api -->
<dependency>
<groupId>com.nsn.cumulocity.clients-java</groupId>
<artifactId>microservice-dependencies</artifactId>
<version>${c8y.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot-dependencies.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.nsn.cumulocity.clients-java</groupId>
<artifactId>microservice-package-maven-plugin</artifactId>
<version>${c8y.version}</version>
<executions>
<execution>
<id>package</id>
<phase>package</phase>
<goals>
<goal>package</goal>
</goals>
<configuration>
<name>hello-world</name>
<image>hello-world</image>
<encoding>UTF-8</encoding>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Building the microservice
To build the ZIP file, use the following command:
$mvn clean install
After a successful build you will be provided with a ZIP file in the target directory. The ZIP can be deployed to the platform as described in the Deployment section.
Running microservice locally
In order to test the microservice for the calls from the microservice to Cumulocity, you can run the docker container locally.
To verify calls from Cumulocity to the microservice, the microservice must be deployed.
To run a microservice which uses Cumulocity API locally you need the following:
- URL address of the Cumulocity host of your tenant
- Authorization header = "Basic {Base64({username}:{password})}"
- Tenant - tenant ID
Step 1 - Create application
If the application does not exist, create a new application on a platform:
POST {URL}/application/applications
HEADERS:
"Authorization": "{AUTHORIZATION}"
"Content-Type": "application/vnd.com.nsn.cumulocity.application+json"
"Accept: application/vnd.com.nsn.cumulocity.application+json"
BODY:
{
"name": "{APPLICATION_NAME}",
"type": "MICROSERVICE",
"key": "{APPLICATION_NAME}-microservice-key"
}
Example:
$curl -X POST -s \
-d "{"name":"hello-microservice-1","type":"MICROSERVICE","key":"hello-microservice-1-key"}" \
-H "Authorization: {AUTHORIZATION}" \
-H "Content-Type: application/vnd.com.nsn.cumulocity.application+json" \
-H "Accept: application/vnd.com.nsn.cumulocity.application+json" \
"{URL}/application/applications"
Example response:
{
"availability": "PRIVATE",
"id": "{APPLICATION_ID}",
"key": "{APPLICATION_NAME}-microservice-key",
"manifest": {
"imports": [],
"noAppSwitcher": true
},
"name": "{APPLICATION_NAME}",
"owner": {
"self": "...",
"tenant": {
"id": "..."
}
},
"requiredRoles": [],
"roles": [],
"self": "..",
"type": "MICROSERVICE"
}
If the application has been created correctly, you can get the application ID from the response.
Step 2 - Acquire microservice bootstrap user
GET {URL}/application/applications/{APPLICATION_ID}/bootstrapUser
HEADERS:
"Authorization": {AUTHORIZATION}
"Content-Type": application/vnd.com.nsn.cumulocity.user+json
Example response:
HTTP/1.1 200 Ok
Content-Type: application/vnd.com.nsn.cumulocity.user+json
{
"tenant": "...",
"name": "...",
"password": "..."
}
Step 3 - Run microservice locally
The image is already added to the local docker repository during the build. List all the docker repository images available:
$ docker images
After you find the image in the list, run the docker container for the microservice by providing the baseurl and the bootstrap user credentials:
$ docker run -e C8Y_BASEURL={URL} -e C8Y_BOOTSTRAP_TENANT={BOOTSTRAP_TENANT} -e C8Y_BOOTSTRAP_USER={BOOTSTRAP_USERNAME} -e C8Y_BOOTSTRAP_PASSWORD={BOOTSTRAP_USER_PASSWORD} -e C8Y_MICROSERVICE_ISOLATION=MULTI_TENANT -i -t {DOCKER_REPOSITORY_IMAGE}:{TAG}
Step 4 - Subscribe to microservice
POST {URL}/tenant/tenants/{TENANT_ID}/applications
HEADERS:
"Authorization": "{AUTHORIZATION}"
BODY:
{"application":{"id": "{APPLICATION_ID}"}}
Example:
curl -X POST -d "{"application":{"id": "{APPLICATION_ID}"}}" \
-H "Authorization: {AUTHORIZATION}" \
-H "Content-type: application/json" \
"{URL}/tenant/tenants/{TENANT_ID}/applications"
Deployment
To deploy a microservice application on an environment you need the following:
- URL address of the Cumulocity host of your tenant
- Authorization header = "Basic {Base64({username}:{password})}"
- Tenant - tenant ID
- ZIP build from previous step for deployment
Step 1 - Create application
If the application does not exist, create a new application on a platform. For details, refer to the "Create application" step in Run microservice locally.
Step 2 - Upload ZIP file
POST {URL}/application/applications/{APPLICATION_ID}/binaries
HEADERS:
"Authorization": "{AUTHORIZATION}"
"Content-Type": "multipart/form-data"
Example:
curl -F "data=@{PATH_TO_ZIP}" \
-H "Authorization: {AUTHORIZATION}" \
"{URL}/application/applications/{APPLICATION_ID}/binaries"
Step 3 - Subscribe to microservice
For details, refer to the "Subscribe to microservice" step in Run microservice locally.
Step 4 - Verify if microservice is running
Now you can verify if your application is running by executing
curl -H "Authorization: {AUTHORIZATION}" \
{URL}/service/hello-world/hello?who=me
The expected result is:
hello me!
Improving the microservice
Now that you have done your first step, check out the section Developing Java Microservice.
Developing Microservices
This document describes microservice SDK features, including annotations, services, configuration files, logging and maven build plugin.
Overview
There are two possible deployment types on the platform:
- Hosted deployment - the default for microservices. For typical use cases the hosted deployment is the suggested one.
- External/legacy deployment - requires custom installation of the platform and agent.
For development and testing purposes one can deploy a microservice on a local docker.
Annotations
The simplest way to add required behavior to your application is to annotate a main class with @MicroserviceApplication.
This is a collective annotation consisting of:
- @SpringBootApplication - comes from spring boot auto configure package
- @EnableContextSupport - is required to use @UserScope, or @TenantScope scopes for method invocations
- @EnableHealthIndicator - provides standard health endpoint used by the platform to monitor microservice availability
- @EnableMicroserviceSecurity - provides standard security mechanism, verifying user and roles against the platform
- @EnableMicroserviceSubscription - is responsible for subscribing microservices to the platform, updating metadata and listen to tenant subscription change events
- @EnableMicroservicePlatformInternalApi - injects the platform API services into spring context for a microservice to use
Context support
The following section describes context support as utility tool for the user management described in General aspects of microservices in Cumulocity.
@UserScope and @TenantScope at type level annotation indicate that a bean created from class will be created in the scope defined. The user scope implies using tenant platform user credentials for platform calls. The tenant scope implies using service user credentials.
Example of injecting a bean into the tenant scope is available in the platform API module as follows:
@TenantScope
public EventApi eventApi(Platform platform) throws SDKException {
return platform.getEventApi();
}
And then sample utilization of the bean can be as follows:
@Autowired
private PlatformProperties platformProperties;
@Autowired
private ContextService<MicroserviceCredentials> contextService;
@Autowired
private EventApi eventApi;
public PagedEventCollectionRepresentation get10Events() {
return contextService.callWithinContext(
(MicroserviceCredentials) platformProperties.getMicroserviceBoostrapUser()
, new Callable<PagedEventCollectionRepresentation>(){
public PagedEventCollectionRepresentation call(){
return eventApi.getEvents().get(10);
}
});
}
Microservice security
The @EnableMicroserviceSecurity annotation sets up the standard security configuration for microservices, which requires basic authorization for all endpoints (except for health check endpoint configured using @EnableHealthIndicator). A developer can secure its endpoints using standard spring security annotations e.g. @PreAuthorize("hasRole('ROLE_A')") and user's permissions will be validated against user's roles stored on the platform.
Microservice subscription
The microservice subscription module is responsible for two main features:
- registration
- tenant subscription event listening
The default behavior for the package is self-registration, which means that after you run the application it will try to register and use generated credentials for the communication with the platform. The self-registration is required to correctly deploy the microservice on the platform.
The other way to register an application to the platform is to do it manually by creating a new application on the platform with the same application name and providing the following properties into the microservice:
application.name={application_name}
C8Y.bootstrap.register=false
C8Y.bootstrap.tenant={tenant}
C8Y.bootstrap.user={user}
C8Y.bootstrap.password={password}
To create an application and acquire credentials, refer to:
The subscription package provides means to monitor and act upon changes in tenant subscriptions to a microservice. To add a custom behavior a developer can add an event listener for MicroserviceSubscriptionAddedEvent and MicroserviceSubscriptionRemovedEvent like in the following example:
@EventListener
public void onAdded(MicroserviceSubscriptionAddedEvent event{
log.info("subscription added for tenant: " + event.getCredentials().getTenant());
}
On application startup the MicroserviceSubscriptionAddedEvent is triggered for all subscribed tenants.
Platform API
The package consists of a number of services that are build and injected into spring context. A developer can use them to perform basic operations against the platform. The beans are built based on properties read from a file. For hosted deployment, most of the properties are provided by the platform.
The API provides the following services:
- Alarm - AlarmApi
- AuditRecord - AuditRecordApi
- CepModule - CepApi
- Operation - DeviceControlApi
- Event - EventApi
- ExternalID - IdentityApi
- Binary - BinariesApi
- ManagedObject - InventoryApi
- Measurement - MeasurementApi
The API provides basic CRUD methods, see alarm interface example below:
AlarmRepresentation create(final AlarmRepresentation alarm)
Future createAsync(final AlarmRepresentation alarm)
AlarmRepresentation getAlarm(final GId gid)
AlarmCollection getAlarms()
AlarmCollection getAlarmsByFilter(final AlarmFilter filter)
AlarmRepresentation update(final AlarmRepresentation alarm)
Sample usage:
@Autowired
private AlarmApi alarms;
public AlarmRepresentation addHelloAlarm(){
AlarmRepresentation alarm = new AlarmRepresentation();
alarm.setSeverity("CRITICAL");
alarm.setStatus("Hello");
return alarms.create(alarm);
}
Configuration files
The property file used by the hosted deployment must be located in src/main/resources/application.xml.
For external/legacy deployment, the following paths will be searched in order to find a property file specific for the environment the application is run on:
- {UPPERCASE(application_name)}_CONF_DIR/.{application_name}
- {UPPERCASE(application_name)}_CONF_DIR/{application_name}
- {user/home}/.{application_name}
- {user/home}/{application_name}
- {CONF_DIR}/.{application_name}
- {CONF_DIR}/{application_name}
- /etc/{application_name}
Properties used by a microservice are:
application.name - Application name
C8Y.bootstrap.register - Indicates whether microservice should follow self-registration process. True by default
C8Y.baseURL - Address of the platform. Provided by the deployment process
C8Y.baseURL.mqtt - Address of the MQTT service. Provided by the platform
C8Y.bootstrap.tenant - Microservice owner tenant
C8Y.bootstrap.user - User used by microservice, or by microservice registration process
C8Y.bootstrap.password - Password used by microservice, or by microservice registration process
C8Y.bootstrap.delay - Subscription refresh delay
C8Y.bootstrap.initialDelay - Initial subscription delay
C8Y.microservice.isolation - Microservice isolation. Only PER_TENANT or MULTI_TENANT values are available. MULTI_TENANT by default
Logging
For hosted deployment the standard output should be used.
For external/legacy deployment logging into the application implies using spring logging described in this article.
The following locations are searched for log-back file:
- {UPPERCASE(application_name)}_CONF_DIR/.{application_name}/logging.xml
- {UPPERCASE(application_name)}_CONF_DIR/{application_name}/logging.xml
- {user/home}/.{application_name}/logging.xml
- {user/home}/{application_name}/logging.xml
- {CONF_DIR}/.{application_name}/logging.xml
- {CONF_DIR}/{application_name}/logging.xml
- /etc/{application_name}/logging.xml
Maven plugin
The package module provides a maven plugin to prepare a ZIP file required by the microservice deployment, with simple configuration. The build requires an executable jar. To create one, a developer can use spring-boot-maven-plugin.
An example with minimum configuration is presented below:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>${main.class}</mainClass>
</configuration>
</plugin>
<plugin>
<groupId>com.nsn.cumulocity.clients-java</groupId>
<artifactId>microservice-package-maven-plugin</artifactId>
<version>9.0.0</version>
<executions>
<execution>
<id>package</id>
<phase>package</phase>
<goals>
<goal>package</goal>
</goals>
<configuration>
<name>hello-world</name>
<encoding>UTF-8</encoding>
<rpmSkip>true</rpmSkip>
<containerSkip>false</containerSkip>
</configuration>
</execution>
<execution>
<id>microservice-package</id>
<phase>package</phase>
<goals>
<goal>microservice-package</goal>
</goals>
<configuration>
<name>hello-world</name>
<image>hello-world</image>
<encoding>UTF-8</encoding>
<skip>false</skip>
</configuration>
</execution>
</executions>
</plugin>
Package goal
The package plugin is responsible for creation of a docker container, rpm file and for creating a ZIP file, that can be deployed on the platform. It can be configured with the following parameters:
- name (alias package.name) - defaults to project.artifactId
- description (alias package.description) - defaults to project.description
- jvmArgs (alias agent-package.jvmArgs) - jvm-gc arguments. The default value is
-XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+ScavengeBeforeFullGC -XX:+CMSScavengeBeforeRemark
". Will be overwritten if other options are provided. - arguments (alias agent-package.arguments) - arguments passed on Java application startup
- encoding (alias project.build.sourceEncoding) - defaults to UTF-8
- heap (alias agent-package.heap) - defaults to min = 128MB max = 384MB
- perm (alias agent-package.perm) - defaults to min = 64MB max = 128MB
- skip (alias skip.agent.package) - to skip the whole packaging part
- rpmSkip (alias skip.agent.package.rpm) - to skip rpm file creation. False by default
- containerSkip (alias skip.agent.package.container) - to skip docker image creation. True by default
- manifestFile - points to a manifest file location. Default value: ${basedir}/src/main/configuration/cumulocity.json
Example configuration:
<configuration>
<name>hello-world</name>
<encoding>UTF-8</encoding>
<rpmSkip>true</rpmSkip>
<containerSkip>false</containerSkip>
<manifestFile>${basedir}/src/main/microservice/cumulocity.json</manifestFile>
</configuration>
Push goal
The push plugin is responsible for pushing the docker image to a registry. The registry can be configured by:
- containerSkip (alias skip.agent.package.container) - prevents the push to execute. True by default
- registry (alias agent-package.container.registry) - docker registry address
Example configuration:
<configuration>
<registry>http://{yourregistry.com}</registry>
<containerSkip>false</containerSkip>
</configuration>
Upload goal
Microservice upload goal is responsible for deploying the microservice to a server.
We have three options to configure server url and credentials:
- settings.xml - maven global configuration placed at ~/.m2/settings.xml
- pom.xml - maven project configuration file
- command line
All three ways can be used together, i.e. goal partially can be configured in settings.xml and partially in pom.xml. In case of conflicts the command line configuration has the highest priority and settings xml configuration the lowest.
To upload a microservice to the server you need to configure the following properties:
- url - Mandatory URL that will be used for deployment. Empty by default.
- username - Mandatory tenant name and user name used for authorization. Empty by default.
- password - Mandatory password used for authorization. Empty by default.
- name - Optional name of uploaded application. By default the same as "package.name" property or "artifactId" if "package.name" is not provided.
settings.xml
To configure the goal in the settings.xml file we need to add the server configuration as follows:
<server>
<id>microservice</id>
<username>demos/username</username>
<password>******</password>
<configuration>
<url>https://demos.cumulocity.com</url>
</configuration>
</server>
pom.xml
To configure the plugin in the pom.xml file we need to add the server configuration as follows.
<plugin>
<groupId>com.nsn.cumulocity.clients-java</groupId>
<artifactId>microservice-package-maven-plugin</artifactId>
<configuration>
<application>
<name>cep</name>
</application>
<!-- please note that the credentials are optional if they are already configured in settings.xml -->
<credentials>
<url>https://demos.cumulocity.com</url>
<username>demos/username</username>
<password>******</password>
</credentials>
</configuration>
</plugin>
Command line
To pass the configuration only to the particular build, run
mvn microservice:upload -Dupload.application.name=cep -Dupload.url=https://demos.cumulocity.com -Dupload.username=demos/username -Dupload.password=******
Deployment
Hosted deployment
**Info**: For your convenience we have prepared a utility deployment script available [here](/guides/reference/microservice-package).
To deploy an application on an environment you need the following:
- URL address of your tenant
- Authorization header = "Basic {Base64({username}:{password})}"
- Tenant - tenant ID
- ZIP build from previous step
Step 1 - Create application
If the application does not exist, create a new application on the platform:
POST /application/applications
Host: ...
Authorization: Basic xxxxxxxxxxxxxxxxxxx
Content-Type: "application/json"
BODY:
{
"name": "{APPLICATION_NAME}",
"type": "MICROSERVICE",
"key": "{APPLICATION_NAME}-microservice-key"
}
Example:
$curl -X POST -s \
-d "{"name":"hello-microservice-1","type":"MICROSERVICE","key":"hello-microservice-1-key"}" \
-H "Authorization: {AUTHORIZATION}" \
-H "Content-type: application/json" \
"{URL}/application/applications"
If the application has been created correctly, you can get the application ID by invoking:
GET /application/applicationsByName/{APPLICATION_NAME}
Host: ...
Authorization: Basic xxxxxxxxxxxxxxxxxxx
Accept: "application/json"
Example:
curl -H "Authorization:{AUTHORIZATION}" \
{URL}/application/applicationsByName/hello-world
Step 2 - Upload zip file
POST /application/applications/{APPLICATION_ID}/binaries
Host: ...
Authorization: Basic xxxxxxxxxxxxxxxxxxx
Content-Type: "multipart/form-data"
Example:
curl -F "data=@{PATH_TO_ZIP}" \
-H "Authorization: {AUTHORIZATION}" \
"{URL}/application/applications/{APPLICATION_ID}/binaries"
Step 3 - Subscribe to microservice
POST /tenant/tenants/$TENANT/applications
Host: ...
Authorization: Basic xxxxxxxxxxxxxxxxxxx
Content-Type: "multipart/form-data"
BODY:
{"application":{"id": "{APPLICATION_ID}"}}
Example:
curl -X POST -d "{"application":{"id": "{APPLICATION_ID}"}}" \
-H "Authorization: {AUTHORIZATION}" \
-H "Content-type: application/json" \
"{URL}/tenant/tenants/{TENANT}/applications"
Local docker deployment
To deploy the application on a local docker, one needs to inject the environment variables into a container. This is done via the docker run -e parameter. The full description of available parameters is available in Microservice runtime > Environment variables in the Reference guide.
An example execution could be:
docker run -e "C8Y_BASEURL={C8Y_BASEURL}" -e "C8Y_BASEURL_MQTT={C8Y_BASEURL_MQTT}" {IMAGE_NAME}
Monitoring
To check if a hosted microservice is running successfully, the microservice's health endpoint can be checked. This endpoint is enabled by default for all microservices that are developed using Java Microservice SDK.
GET {URL}/service/{APPLICATION_NAME}/health
Example response:
HTTP/1.1 200
{
"status":"UP"
}
or
HTTP/1.1 503
{
"status":"DOWN"
}
Developing Java clients for services
This section describes the Cumulocity Email and SMS API and shows how to access them using the Cumulocity Java Client.
Using the services platform
The "services platform interface" is responsible for connecting to the Services (SMS) API from Java.
ServicesPlatform platform = new ServicesPlatformImpl("<<URL>>", new CumulocityCredentials("<<tenant>>", "<<user>>", "<<password>>", "<application key>"));
The URL pointing to the platform must be of the form {tenant}.cumulocity.com
, for example https://demos.cumulocity.com
, which will process all the API requests.
Info: You need to have appropriate credentials to be able to access the Services API from outside, see example above.
Accessing the SMS Messaging API
In the following section you will learn how to send and receive SMS messages via the Java Client API.
The following code snippet shows how to obtain a handle to the SMS API from Java:
SmsMessagingApi smsMessagingApi = platform.getSmsMessagingApi();
Using this handle, you can send and retrieve the SMS messages from Java by calling its functions.
Prerequisites
Assigning required roles
To use the SMS messaging API the user should have the required roles such as 'SMS_ADMIN' for sending and 'SMS_READ' for receiving messages.
Refer to Administration > Managing permissions in the User guide.
Choosing a SMS provider
OpenIT
OpenIT credentials can be assigned using the Administration application. Click OpenIT credentials in the navigator and save these credentials for your tenant.
Note that receiving messages and receiving specific messages are not supported for this provider.
Jasper Control Center
Refer to Jasper Control Center for information about how to set the credentials.
Ericsson
For Ericsson, use our Rest API to store tenant options separately for each key:
POST /tenant/options
Host: ...
Authorization: Basic ...
Provider:
{
"category": "messaging",
"key": "provider",
"value": "ericsson-dcp"
}
Base URL:
{
"category": "messaging",
"key": "ericsson-dcp.baseUrl",
"value": "<url>"
}
Username:
{
"category": "messaging",
"key": "ericsson-dcp.username",
"value": "<username>"
}
Password:
{
"category": "messaging",
"key": "ericsson-dcp.password",
"value": "<password>"
}
Sender address:
{
"category": "messaging",
"key": "sms.senderAddress",
"value": "<The phone number all SMS will be sent from (provided by Ericsson DCP)>"
}
Sender name:
{
"category": "messaging",
"key": "sms.senderName",
"value": "<The name associated with the phone number>"
}
Note that receiving specific messages is not supported for this provider.
Telia Sonera
For Telia Sonera, use our Rest API to store tenant options separately for each key:
POST /tenant/options
Host: ...
Authorization: Basic ...
Provider:
{
"category": "messaging",
"key": "provider",
"value": "soneraoma"
}
Username of Telia Sonera Client Application:
{
"category": "messaging",
"key": "soneraoma.username",
"value": "<username>"
}
Password assigned for Telia Sonera Client Application:
{
"category": "messaging",
"key": "soneraoma.password",
"value": "<password>"
}
Telia Sonera OAUTH Service Endpoint:
{
"category": "messaging",
"key": "soneraoma.authUrl",
"value": "<OAUTH Service endpoint url as appears in TS Application Profile, e. g., https://api.sonera.fi/autho4api/v1>"
}
Telia Sonera Messaging OMA v1 Endpoint:
{
"category": "messaging",
"key": "soneraoma.messagingUrl",
"value": "<Messaging endpoint url as appears in TS Application Profile, e. g., https://api.sonera.fi/sandbox/messaging/v1>"
}
Note that receiving messages and receiving specific messages is not supported for this provider.
Tropo
For Tropo, use our Rest API to store tenant options separately for each key
POST /tenant/options
Host: ...
Authorization: Basic ...
Provider:
{
"category": "messaging",
"key": "provider",
"value": "tropo"
}
Base URL:
{
"category": "messaging",
"key": "tropo.baseUrl",
"value": "<url>"
}
Credentials:
{
"category": "messaging",
"key": "tropo.credentials",
"value": "<credentials>"
}
Sender address:
{
"category": "messaging",
"key": "sms.senderAddress",
"value": "cumulocity"
}
Sender name:
{
"category": "messaging",
"key": "sms.senderName",
"value": "cumulocity"
}
Note that receiving messages and receiving specific message is not supported for this provider.
Sending a message
To send a SMS message using the API, prepare the message with the "send message request builder" and call the "send message" function of the API with the message.
SendMessageRequest smsMessage = SendMessageRequest.builder()
.withSender(Address.phoneNumber("<phone number>"))
.withReceiver(Address.phoneNumber("<phone number>"))
.withMessage("<message text>")
.build();
smsMessagingApi.sendMessage(smsMessage);
Receiving all messages
Not every SMS provider supports receiving messages.
To receive all SMS messages you can use the API as follows:
smsMessagingApi.getAllMessages(Address.phoneNumber("<phone number>"));
Receiving a specific message
Not every SMS provider supports receiving messages.
To receive a specific SMS message you can use the API as follows:
smsMessagingApi.getMessage(Address.phoneNumber("<phone number>"), "<message id>");
SMS management endpoints
To accomplish the same behaviour, Rest API can be used.
Sending message:
POST /service/messaging/smsmessaging/outbound/tel:<sender phone number>/requests
Host: ...
Authorization: Basic ...
Content-Type: application/json
{
"outboundSMSMessageRequest": {
"address": ["tel:<phone number>"],
"senderAddress": "tel:<phone number>",
"outboundSMSTextMessage": {
"message": "<message text>"
},
"receiptRequest": {
"notifyUrl": <notify url>,
"callbackData": <callback data>
},
"senderName": <sender name>
}
}
Receiving all messages:
GET /service/messaging/smsmessaging/inbound/registrations/tel:<receiver phone number>/messages
Host: ...
Authorization: Basic ...
HTTP/1.1 200 OK
{
"inboundSMSMessageList": [
{
"inboundSMSMessage": {
"dateTime": "<date>",
"destinationAddress": "<destination address>",
"messageId": "<message id>",
"message": "<message>",
"resourceURL": "<resource url>",
"senderAddress": "<sender address>"
}
]
}
Receiving a specific message:
GET /service/messaging/smsmessaging/inbound/registrations/tel:<receiver phone number>/messages/<message id>
Host: ...
Authorization: Basic ...
HTTP/1.1 200 OK
{
"inboundSMSMessage": {
"dateTime": "<date>",
"destinationAddress": "<destination address>",
"messageId": "<message id>",
"message": "<message>",
"resourceURL": "<resource url>",
"senderAddress": "<sender address>"
}
}
Troubleshooting
This section describes common problems and their solutions.
SSL or certificate errors
You can use both HTTP and HTTPS from the Java client libraries. To use HTTPS, you may need to import the Cumulocity production certificate into your Java runtime environment. Download the certificate and import it using the following command on the command line:
$JAVA_HOME/bin/keytool -import -alias cumulocity -file cumulocity.com.crt -storepass changeit
Answer "yes" to the question "Trust this certificate? [no]:".
Use the following argument to run Java:
-Djavax.net.ssl.trustStore=<<home directory>>/.keystore
If you use Eclipse/OSGi, open the Run Configurations... dialog in the Run menu. Double-click OSGi Framework, then open the Arguments tab on the right side. In the VM arguments text box, add the above parameter.
Since Java ships with its own set of trusted root certificates, you might still get the error message:
java.security.cert.CertificateException: Certificate Not Trusted
In this case, make sure that the Go Daddy Certificate Authority (CACert) is available for your JAVA environment using:
keytool -import -v -trustcacerts -alias root -file gd_bundle.crt -keystore $JAVA_HOME/lib/security/cacerts
gd_bundle.crt can be downloaded directly from the GoDaddy repository.
When I install the SDK, Eclipse complains about compatibility problems
Make sure that you use the "Target Platform" preferences page to install the SDK as described in the instructions. "Install New Software" installs software into your running Eclipse IDE, but we need to install the SDK as a separate server software.
"Expected to find an object at table index" when running an agent or application
This error occurs due to a bug in particular Eclipse versions. As a workaround, select Run from the main menu and then Run Configurations .... On the left, select the launch configuration that you have been using, e.g. OSGi Framework. On the right, click the Arguments tab. Append a " -clean" to the Program Arguments and click Apply.
The agent or application won't start
Check if all required plug-ins are checked in your launch configuration. Go to Run > Run Configurations and select the OSGi Framework launch configuration. Click Select All and try running again.
Check if the required plug-ins are started. While the application or agent is running, type "ss" into the console and hit the return key. All listed plug-ins should be either in the ACTIVE or RESOLVED state.
Check if you are using the correct target platform. Go to the Target Platform page in the preferences and check if "Cumulocity runtime" is checked.
The agent will not compile, I get "Access Restriction" messages
This error may be caused because of a missing package import. Navigate to the Dependencies tab of the project manifest file and check if the package of the type that contains the method giving the access restriction is present in the Import-Package section.
You can find the package by opening the declaration of the method (right-click and select Open Declaration from the context menu).
When starting an application, I get "address already in use" messages
Check if you are running another instance of the application. Click on the Display Selected Console icon in the console toolbar (the terminal icon) to browse through your consoles. Terminate other running instances by clicking the red Stop icon in the toolbar.
Under Unix/MacOSX you can also use the lsof command to see which process is using a particular port. For example, to see which process is using TCP port 8080 enter:
lsof -i tcp:8080
which will return something like
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME java 12985 pitchfor 45u IPv6 0x077c76d0 0t0 TCP *:8080 (LISTEN)
so process 12985 is using that port which can then be killed if necessary.