Online status not getting updating in the device managed object

We are facing the issue, where we are not getting online statues for a device even though the device is getting the measurements every minute. We are using cumulocity sdk to send the measurements to the deviceas shown below:

		MeasurementRepresentation createMr = new MeasurementRepresentation();
		createMr.set("measurement",xyz);
		createMr.setSource(xxx);
		createMr.setType(xxx);
		createMr.setDateTime(dateTime);
		measurementApi.create(createMr);

If we use RestApi it is working fine. We had posted the question https://tech.forums.softwareag.com/t/device-availability-status-not-changing-when-measurments-created-using-sdk-api/294696/2
and got few replies.
One was removing the X-Cumulocity-Application-Key header from the request and sending the empty PUT requests to update the status manually. For the first one, we don’t have sdk support to remove the X-Cumulocity-Application-Key header and second I tried id did not work. Since it is an immediate issue which we have to fulfill the client request, can some body provide a solution for this one

As explained in your last question, the microservice SDK provides means to remove the X-Cumulocity-Application-Key header. It just doesn’t work through the MeasurementApi class itself but through the context.

1 Like

As Philipp has mentioned this can be solved by using the Microservice SDK and updating the context in which you execute the creation of a new measurement:

return microserviceSubscriptionsService.callForTenant(tenantId, () -> {
	// remove application header from context
	final MicroserviceCredentials clonedContext = new MicroserviceCredentials(
			contextService.getContext().getTenant(),
			contextService.getContext().getUsername(), contextService.getContext().getPassword(),
			contextService.getContext().getOAuthAccessToken(), contextService.getContext().getXsrfToken(),
			contextService.getContext().getTfaToken(), null);
	
	return contextService.callWithinContext(clonedContext, () -> {
		try {
			return measurementApi.create(measurementRepresentation);
		} catch (SDKException e) {
			e.printStackTrace();
		}
	
		return null;
	});
});

Make sure to inject MicroserviceSubscriptionsService microserviceSubscriptionsService and ContextService<MicroserviceCredentials> contextService.



Christian Guether

1 Like

Hi @Christian_Guether , I have tried the above code by creating a different context to insert the MeasurementRepresentation. But it did not work.

Can you share your code block? For me it is working like expected.

Hi @Stefan_Witschel

Please find the method below that I am using to insert the MeasurementRepresentation

    private void insertMeasurement() {
       microserviceSubscriptionsService.callForTenant(contextService.getContext().getTenant(), () -> {
            final MicroserviceCredentials clonedContext = new MicroserviceCredentials(contextService.getContext().getTenant(), contextService.getContext().getUsername(), contextService.getContext().getPassword(), contextService.getContext().getOAuthAccessToken(), contextService.getContext().getXsrfToken(), contextService.getContext().getTfaToken(), null);

            contextService.callWithinContext(clonedContext, () -> {
                try {
                    MeasurementRepresentation measurementToInjest = // createMeasurementRepresentation
                    MeasurementRepresentation mrCreated = measurementApi.create(measurementToInjest);
                } catch (SDKException e) {
                   log.error("The current exception is "+e.getStackTrace());
                }
                return null;
            });
            return null;
        });
    }

As you don’t return anything you don’t need to run callForTenant. Instead replace it with runForTenant and remove the return part.

Everything else looks fine.
Did you set the required Interval on your device? Otherwise the connection status will not be updated.

For various reasons the context may be cached (see: cumulocity-clients-java/microservice/context/src/main/java/com/cumulocity/microservice/context/annotation/EnableContextSupportConfiguration.java at develop · SoftwareAG/cumulocity-clients-java · GitHub)

In this we don’t not use the app key as part of the combined key for retrieving said context again. This may lead to the same context being returned again without the changes made. In order to circumvent this behaviour you can also reset the XSRF token to a value of your choice (ex: “PLACEHOLDER”) since it is not relevant when sending requests from a microservice to Cumulocity within the same environment.

The resulting code will then look like this:

private MicroserviceCredentials createContextWithoutApiKey(MicroserviceCredentials source) {
  return new MicroserviceCredentials(
    source.getTenant(),
    source.getUsername(),
    source.getPassword(),
    source.getOAuthAccessToken(),
    "PLACEHOLDER", //added to replace context, check: com.cumulocity.microservice.context.annotation.EnableContextSupportConfiguration.contextScopeConfigurer
    source.getTfaToken(),
    null
  );
}

Then you can make use of it in your measurement sending implementation like this:

        MicroserviceCredentials noAppKeyContext = createContextWithoutApiKey(contextService.getContext());
        contextService.callWithinContext(noAppKeyContext, () -> measurementApi.create(createMr));
1 Like

Thanks @Philipp_Emmel , Will do these changes in my code as well