How to get host name in Java SDK

Hello All,

I am using below code to get the host name in local development and i am getting below response for dev and prod.

Measurement Subscription code

private void registerForMeasurementUpdates(PlatformParameters platform) {
		final MeasurementNotificationSubscriber subscriber = new MeasurementNotificationSubscriber(platform);
		
		measurementSubscription = subscriber.subscribe(deviceId, new SubscriptionListener<>() {
			@Override
			public void onNotification(Subscription<String> arg0, MeasurementNotification notification) {
				final MeasurementRepresentation measurement = jsonParser.parse(MeasurementRepresentation.class,
						json.forValue(notification.getData()));

        String hostURL =  platform.getHost().toString();

For dev tenant- it is giving

https://dev.com/

For prod tenant - it is giving

https://prod.1.com/

Giving correct host name.

When i deploy this microservice in dev tenant, the same code is giving different host name

http://cumulocity:8111/

Do i have to use the method in some different way.

Do let me know , if there is any other way to get host name.

Hi Prakash,

as the microservice is running inside a Docker container, you get the hostname the Docker host provides to the container. Can you explain what you want to achieve? I guess you do not really want the host name of the microservice in the first place.

Edit: have a look at the currentTenant endpoint. The response contains the domain name:
https://cumulocity.com/api/core/10.18.0/#operation/getCurrentTenantResource

Best regards,
Harald

1 Like

Hello Harald,

Let me explain you my use case.
I am building one microservice, which will be deployed on different tenant. For the development phase i have provided the tenant details and other information through application-dev.properties file like below

cumulocity configuration for running localy and connecting to cumulocity
application.name=xyz-service
C8Y.bootstrap.register=true
C8Y.bootstrap.tenant=t12345
C8Y.baseURL=https://dev.iot.xyz.com
C8Y.bootstrap.user=servicebootstrap_xyz-service
C8Y.bootstrap.password=redacted
C8Y.microservice.isolation=MULTI_TENANT
C8Y.bootstrap.initialDelay=5000
device.id=123456789

tenant.url=https://dev.iot.xyz.com

I am looking for a method in my controller class which can give the host name

Below is the method.

measurementSubscription = subscriber.subscribe(deviceId, new SubscriptionListener<>() {
	@Override
	public void onNotification(Subscription<String> arg0, MeasurementNotification notification) {
		final MeasurementRepresentation measurement = jsonParser.parse(MeasurementRepresentation.class,
				json.forValue(notification.getData()));

string hostURL = platform.getHost().toString();

Above method is not giving the right name of respective tenant when i deploy it on dev or QA.
it is giving

http://cumulocity:8111/

where as i am expecting – https://dev.iot.xyz.com

Thanks
Prakash

calling class

	@Autowired
	private PlatformUtils platformUtils;
		Optional<String> temp = platformUtils.getHost();
			if (temp.isEmpty()) {
				log.error(
						"Unable to extract base url for the tenant. Will not be able to subscribe to notifications... exiting process initialization for tenant: {}. Resolve this issue and resubscribe the microservice",
						tenantId);
				return;
			}

util class

import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.cumulocity.rest.representation.CumulocityMediaType;
import com.cumulocity.sdk.client.RestConnector;
import com.cumulocity.sdk.client.SDKException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;

import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class PlatformUtils {
	@Autowired
	private RestConnector restConnector;
	public String host;
	private ObjectMapper objectMapper = new ObjectMapper();
	private static final String DOMAIN_NAME_FRAGMENT = "domainName";

	public Optional<String> getHost() {
		if (this.host == null || this.host.isEmpty()) {
			log.info("Resolving domain name...");
			Optional<String> tenantStats = getCurrentTenantInfo();
			if (tenantStats.isPresent()) {
				try {
					ObjectNode node = objectMapper.readValue(tenantStats.get(), ObjectNode.class);
					host = node.get(DOMAIN_NAME_FRAGMENT).asText();
				} catch (Exception e) {
					return Optional.empty();
				}
			} else {
				log.error("Could not resolve tenant host");
			}
		}
		return Optional.of(this.host);
	}

	public Optional<String> getCurrentTenantInfo() {
		try {
			return Optional.ofNullable(restConnector.get("/tenant/currentTenant",
					CumulocityMediaType.APPLICATION_JSON_TYPE, String.class));
		} catch (final SDKException e) {
			log.error("Tenant#getCurrentTenant operation resulted in " + e.getMessage(), e);
		}
		return Optional.empty();
	}

	/*
	 * private Optional<TenantRepresentation> getCurrentTenant() { try {
	 * TenantRepresentation tenantRepresentation =
	 * restConnector.get("/tenant/currentTenant",
	 * CumulocityMediaType.APPLICATION_JSON_TYPE, TenantRepresentation.class);
	 * return Optional.ofNullable(tenantRepresentation); } catch (final SDKException
	 * e) { log.error("Tenant#getCurrentTenant operation resulted in " +
	 * e.getMessage(), e); } return Optional.empty(); }
	 */
}

What is the purpose of knowing the host name within a microservice?

Within the microservice always the C8Y_baseURL should be used which is injected as an environment variable and resolved internally to http://cumulocity:8111/ which is intended.

I suggest to NOT implement any logic based on any public host name. This is against any microservice implementation principle. It should be host independent so it can be deployed anywhere.

If you want logic for all the subscribed tenants you should use the MicroserviceSubscriptionService which will inject you all details of the tenants where the microservice is subscribed to. Mainly the tenantID is used as a key.

In short: In most cases you don’t need the host name and, if implemented, it leads to bad design of your microservice e.g. establishing unnecessary new connections using the host name etc.