{"id":45026,"date":"2016-06-29T16:02:25","date_gmt":"2016-06-29T13:02:25","guid":{"rendered":"https:\/\/www.altoros.com\/blog\/?p=45026"},"modified":"2019-07-09T18:12:30","modified_gmt":"2019-07-09T15:12:30","slug":"using-time-series-in-a-spring-boot-app-on-predix","status":"publish","type":"post","link":"https:\/\/www.altoros.com\/blog\/using-time-series-in-a-spring-boot-app-on-predix\/","title":{"rendered":"Using Time Series in a Spring Boot App on Predix"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_79_2 counter-hierarchy ez-toc-counter ez-toc-transparent ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/www.altoros.com\/blog\/using-time-series-in-a-spring-boot-app-on-predix\/#Introduction_to_Time_Series\" >Introduction to Time Series<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/www.altoros.com\/blog\/using-time-series-in-a-spring-boot-app-on-predix\/#Setting_up_the_services\" >Setting up the services<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/www.altoros.com\/blog\/using-time-series-in-a-spring-boot-app-on-predix\/#Working_with_Time_Series\" >Working with Time Series<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/www.altoros.com\/blog\/using-time-series-in-a-spring-boot-app-on-predix\/#A_query_controller\" >A query controller<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/www.altoros.com\/blog\/using-time-series-in-a-spring-boot-app-on-predix\/#An_ingestion_controller\" >An ingestion controller<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/www.altoros.com\/blog\/using-time-series-in-a-spring-boot-app-on-predix\/#Implementing_OAuth2_authorization\" >Implementing OAuth2 authorization<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/www.altoros.com\/blog\/using-time-series-in-a-spring-boot-app-on-predix\/#Running_the_application\" >Running the application<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/www.altoros.com\/blog\/using-time-series-in-a-spring-boot-app-on-predix\/#Further_reading\" >Further reading<\/a><\/li><\/ul><\/nav><\/div>\n<h3><span class=\"ez-toc-section\" id=\"Introduction_to_Time_Series\"><\/span>Introduction to Time Series<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p><img decoding=\"async\" src=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2019\/07\/using-predix-time-series-in-a-spring-boot-app.jpg\" alt=\"using-predix-time-series-in-a-spring-boot-app\" width=\"140\" style=\"margin: 0px 0px 20px 20px;\" class=\"alignright size-full wp-image-45027\" \/><\/p>\n<p>User Account and Authentication (<a href=\"https:\/\/www.predix.io\/services\/service.html?id=1172\" target=\"_blank\" rel=\"noopener noreferrer\">UAA<\/a>) is an identity management service in Cloud Foundry, used as an OAuth2 provider by the GE Predix platform. Being responsible for managing timed measurements, <a href=\"https:\/\/www.predix.io\/services\/service.html?id=1177\" target=\"_blank\" rel=\"noopener noreferrer\">Time Series<\/a>, in its turn, enables to efficiently and concurrently store data, as well as quickly retrieve it.<\/p>\n<p>The Time Series service consists of two components: Data Ingestion and Data Query. The data-ingestion layer provides the ability to ingest real-time streaming data via WebSockets. The query API allows you to query data using a REST web service and supports grouping of data points by tags, time ranges, or values, and aggregations.<\/p>\n<p>Both the ingestion and query requests must be authorized. The authorization in Time Series is based on two HTTP headers: <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">Authorization<\/code> and <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">Predix-Zone-Id<\/code>. The first one is the OAuth2 bearer token from the UAA instance bound to Time Series. The second header is the GUID of the same Time Series instance.<\/p>\n<p>The ingestion of measurements is typically done by applications automatically, and users do not participate in authentication. So, for authentication, we will use the OAuth2 <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">Client Credentials<\/code> grant type that does not require interaction with a user.<\/p>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Setting_up_the_services\"><\/span>Setting up the services<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>In this example, the services are configured from a Windows-based environment. The only Windows-specific command here is <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">findstr<\/code>, which is similar to the UNIX <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">grep<\/code> command.<\/p>\n<p>Before getting started, install the Cloud Foundry and UAA CLIs. If you have already configured a UAA service instance, skip the steps related to it.<\/p>\n<ol>\n<li style=\"margin-bottom: 6px;\">Log in to Cloud Foundry.<\/li>\n<pre style=\"padding-left: 30px;\">cf login<\/pre>\n<li style=\"margin-bottom: 6px;\">Create a UAA service instance.<\/li>\n<pre style=\"padding-left: 30px;\">cf cs predix-uaa Tiered demo-uaa -c \"{\\\"adminClientSecret\\\":\\\"demo@pass\\\"}\"<\/pre>\n<li style=\"margin-bottom: 6px;\">Get the GUID of the UAA instance.<\/li>\n<pre style=\"padding-left: 30px;\">cf curl \/v2\/service_instances?q=name:demo-uaa | findstr \/R \\\"guid\\\"<\/pre>\n<li style=\"margin-bottom: 6px;\">Create a Time Series service instance.<\/li>\n<pre style=\"padding-left: 30px;\">cf cs predix-timeseries Bronze demo-ts -c \"{\\\"trustedIssuerIds\\\":[\\\"https:\/\/a4ba93c9-f73e-4f94-bc1b-24b738151a2b.predix-uaa.run.aws-usw02-pr.ice.predix.io\/oauth\/token\\\"]}\"<\/pre>\n<li style=\"margin-bottom: 6px;\">Get the GUID of the Time Series instance.<\/li>\n<pre style=\"padding-left: 30px;\">cf curl \/v2\/service_instances?q=name:demo-ts | findstr \/R \\\"guid\\\"<\/pre>\n<li style=\"margin-bottom: 6px;\">From <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">uaac<\/code>, target your UAA instance.<\/li>\n<pre style=\"padding-left: 30px;\">uaac target https:\/\/a4ba93c9-f73e-4f94-bc1b-24b738151a2b.predix-uaa.run.aws-usw02-pr.ice.predix.io<\/pre>\n<li style=\"margin-bottom: 6px;\">Log in to the UAA instance.<\/li>\n<pre style=\"padding-left: 30px;\">uaac token client get admin -s demo@pass<\/pre>\n<li style=\"margin-bottom: 6px;\">Create a client with authorities for accessing the Time Series instance.<\/li>\n<pre style=\"padding-left: 30px;\">uaac client add demo-ts-client-id --secret client@pass --authorized_grant_types \"authorization_code,client_credentials,refresh_token,password\" --scope \"uaa.none,openid\" --autoapprove openid --authorities \"openid,uaa.none,uaa.resource,timeseries.zones.1cb45004-46a9-424c-a723-1578437f5078.user,timeseries.zones.1cb45004-46a9-424c-a723-1578437f5078.ingest,timeseries.zones.1cb45004-46a9-424c-a723-1578437f5078.query\"<\/pre>\n<\/ol>\n<p><center><a href=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2019\/07\/predix-time-series-setting-up-services.png\" target=\"_blank\" rel=\"noopener noreferrer\"><img decoding=\"async\" src=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2019\/07\/predix-time-series-setting-up-services.png\" alt=\"predix-time-series-setting-up-services\" width=\"640\" class=\"aligncenter size-full wp-image-45028\" \/><\/a><\/center><\/p>\n<p>The same setup process can be done through the Predix UI:<\/p>\n<ul>\n<li><a href=\"https:\/\/www.predix.io\/console\/\" target=\"_blank\" rel=\"noopener noreferrer\">Creating services<\/a><\/li>\n<li><a href=\"https:\/\/predix-starter.run.aws-usw02-pr.ice.predix.io\/\" target=\"_blank\" rel=\"noopener noreferrer\">Configuring UAA<\/a><\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Working_with_Time_Series\"><\/span>Working with Time Series<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Next, we create a Spring Boot application with a single dependency in the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">pom<\/code> file:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">&lt;dependency&gt;\r\n &lt;groupid&gt;org.springframework.boot&lt;\/groupid&gt;\r\n &lt;artifactid&gt;spring-boot-starter-web&lt;\/artifactid&gt;\r\n&lt;\/dependency&gt;<\/pre>\n<p><\/p>\n<p>This application will do REST calls to the Time Series service, so we need a REST client. We use Spring\u2019s <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">RestTemplate<\/code> for the REST calls to the Time Series service, because it is easy to configure, and it has an extension with a support for OAuth2. We will skip authorization for now and put the required headers as constants in the properties file.<\/p>\n<p>We have already got <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">Predix-Zone-Id<\/code> in the step 5 during the configuration. For <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">Authorization<\/code>, we will put <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">\"Bearer \" + accessToken<\/code> that can be retrieved by using the command below.<\/p>\n<pre style=\"padding-left: 30px;\">uaac token client get demo-ts-client-id -s client@pass\r\nuaac context<\/pre>\n<p>The headers can be added using <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">ClientHttpRequestInterceptor<\/code>.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">@SpringBootApplication\r\npublic class Application {\r\n\r\n@Value(&quot;${demo.timeseries.zoneId}&quot;)\r\nString zoneId;\r\n\r\n@Value(&quot;${demo.timeseries.accessToken}&quot;)\r\nString accessToken;\r\n\r\n@Bean\r\npublic RestTemplate restTemplate(){\r\n   RestTemplate restTemplate = new RestTemplate();\r\n   restTemplate.getInterceptors().add(headersAddingInterceptor());\r\n   return restTemplate;\r\n}\r\n\r\npublic ClientHttpRequestInterceptor headersAddingInterceptor() {\r\n   return (request, body, execution) -&gt; {\r\n      request.getHeaders().set(&quot;Predix-Zone-Id&quot;, zoneId);\r\n      request.getHeaders().set(&quot;Authorization&quot;, &quot;Bearer &quot; + accessToken);\r\n      return execution.execute(request, body);\r\n   };\r\n}\r\n\r\npublic static void main(String&#x5B;] args) {\r\n   SpringApplication.run(Application.class, args);\r\n}\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"A_query_controller\"><\/span>A query controller<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Now, we create a controller that can query data from the Time Series service.<\/p>\n<p>For this demo, there will be a few mapped requests that only make calls to Time Series. A real-life app can collect data using such calls, as well as process and display it to users as different charts.<\/p>\n<p><code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">queryUrlPrefix<\/code> is the URL to the Time Series query endpoint, and it is the same for all applications: <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">https:\/\/time-series-store-predix.run.aws-usw02-pr.ice.predix.io\/v1<\/code>.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">@RestController\r\n@RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE)\r\npublic class QueryController {\r\n\r\n  @Value(&quot;${demo.timeseries.queryUrlPrefix}&quot;)\r\n  private String queryUrlPrefix;\r\n\r\n  @Autowired\r\n  private RestTemplate restTemplate;\r\n\r\n  @ExceptionHandler\r\n  @RequestMapping(produces = MediaType.TEXT_HTML_VALUE)\r\n  public Object exceptionHandler(HttpStatusCodeException e) {\r\n      return e.getResponseBodyAsString();\r\n  }\r\n\r\n  @RequestMapping(&quot;\/latest&quot;)\r\n  public String queryLatestValues() throws Exception {\r\n      String request = &quot;{'tags':&#x5B;{'name':'CPU usage'}]}&quot;;\r\n      return restTemplate.postForEntity(queryUrlPrefix + &quot;\/datapoints\/latest&quot;, request, String.class, emptyMap()).getBody();\r\n  }\r\n\r\n  @RequestMapping(&quot;\/ordered&quot;)\r\n  public String queryOrderedValues() throws Exception {\r\n      String request = &quot;{'start':'1y-ago','tags':&#x5B;{'name':'CPU usage','order':'desc'}]}&quot;;\r\n      return restTemplate.postForEntity(queryUrlPrefix + &quot;\/datapoints&quot;, request, String.class, emptyMap()).getBody();\r\n  }\r\n}<\/pre>\n<p>In addition, we have added <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">exceptionHandler<\/code>, which is very helpful if something goes wrong with the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">restTemplate<\/code> call. In this case, it will return a more detailed message about the error received from the Time Series service to the user.<\/p>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"An_ingestion_controller\"><\/span>An ingestion controller<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>The ingestion controller is also a REST service, but unlike the query controller, it uses WebSockets to send data to the Time Series service. WebSockets in Time Series require the additional <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">Origin<\/code> header that can contain any value.<\/p>\n<p>Here is the utility class that encapsulates connection opening.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">public class WebSocketUtils {\r\n\r\n  public static final String ZONE_ID_HEADER = &quot;Predix-Zone-Id&quot;;\r\n  public static final String LOCALHOST_URL = &quot;http:\/\/localhost\/&quot;;\r\n\r\n  public static Session openWebSocket(String url, Object pojoEndpoint, String zoneId, String accessToken)\r\n          throws DeploymentException, IOException {\r\n      ClientEndpointConfig config = ClientEndpointConfig.Builder.create()\r\n              .configurator(createConfigurator(zoneId, accessToken))\r\n              .build();\r\n      Endpoint endpoint = new PojoEndpointClient(pojoEndpoint, Collections.emptyList());\r\n      WebSocketContainer container = ContainerProvider.getWebSocketContainer();\r\n      return container.connectToServer(endpoint, config, URI.create(url));\r\n  }\r\n\r\n  public static ClientEndpointConfig.Configurator createConfigurator(final String zoneId, final String accessToken) {\r\n      String authorizationToken = &quot;Bearer &quot; + accessToken;\r\n\r\n      return new ClientEndpointConfig.Configurator(){\r\n          @Override\r\n          public void beforeRequest(Map&lt;String, List&lt;String&gt;&gt; headers) {\r\n              addHeader(headers, ZONE_ID_HEADER, zoneId);\r\n              addHeader(headers, HttpHeaders.AUTHORIZATION, authorizationToken);\r\n              addHeader(headers, HttpHeaders.ORIGIN, LOCALHOST_URL);\r\n          }\r\n\r\n          private void addHeader(Map&lt;String, List&lt;String&gt;&gt; headers, String name, String value) {\r\n              headers.computeIfAbsent(name, k -&gt; new ArrayList&lt;&gt;()).add(value);\r\n          }\r\n      };\r\n  }\r\n}<\/pre>\n<p>You can see the application at this stage in <a href=\"https:\/\/github.com\/Altoros\/predix-timeseries-example\/tree\/c310e7cf09b879e5d74c6459b03c7eaa6bc47293\" target=\"_blank\" rel=\"noopener noreferrer\">this GitHub repository<\/a>.<\/p>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Implementing_OAuth2_authorization\"><\/span>Implementing OAuth2 authorization<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Now, it is time to replace the constants with the implementation of the OAuth2 authorization. The following additional dependencies are added.<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">&lt;dependency&gt;\r\n &lt;groupid&gt;org.springframework.boot&lt;\/groupid&gt;\r\n &lt;artifactid&gt;spring-boot-starter-security&lt;\/artifactid&gt;\r\n&lt;\/dependency&gt;\r\n\r\n&lt;dependency&gt;\r\n &lt;groupid&gt;org.springframework.security.oauth&lt;\/groupid&gt;\r\n &lt;artifactid&gt;spring-security-oauth2&lt;\/artifactid&gt;\r\n&lt;\/dependency&gt;<\/pre>\n<p><\/p>\n<p>As it was said above, two headers are needed for the authorization: <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">Predix-Zone-Id<\/code> and <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">Authorization<\/code>. The first one is the GUID of the Time Series instance. It does not change and can be stored as a constant. If an application is deployed to Predix and bound to the Time Series service, the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">Predix-Zone-Id<\/code> header can be retrieved from the application environment variables.<\/p>\n<p><center><a href=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2019\/07\/implementing-oauth2-authorization.png\" target=\"_blank\" rel=\"noopener noreferrer\"><img decoding=\"async\" src=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2019\/07\/implementing-oauth2-authorization.png\" alt=\"implementing-oauth2-authorization\" width=\"640\" class=\"aligncenter size-full wp-image-45029\" \/><\/a><\/center><\/p>\n<p>The <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">Authorization<\/code> header is the OAuth2 bearer token that should be requested from the UAA instance according to the configured grant type. Luckily, this is already implemented in Spring\u2019s <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">OAuth2RestTemplate<\/code>. By default, it is configured to work using the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">Authorization Code<\/code> grant type, so we need to create another instance that will work with the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">Client Credentials<\/code> type.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">@SpringBootApplication\r\n@EnableOAuth2Client\r\n@EnableConfigurationProperties\r\npublic class Application {\r\n\r\n...\r\n@Bean\r\n@ConfigurationProperties(&quot;security.oauth2.client&quot;)\r\npublic ClientCredentialsResourceDetails details() {\r\n return new ClientCredentialsResourceDetails();\r\n}\r\n\r\n@Bean\r\npublic OAuth2RestTemplate restTemplate(OAuth2ClientContext context, ClientCredentialsResourceDetails details) {\r\n OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(details, context);\r\n restTemplate.getInterceptors().add(headersAddingInterceptor());\r\n return restTemplate;\r\n}\r\n...\r\n}<\/pre>\n<p>Next, we add all parameters for the OAuth2 workflow to the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">properties.yml<\/code> file.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">demo.timeseries:\r\nqueryUrlPrefix: https:\/\/time-series-store-predix.run.aws-usw02-pr.ice.predix.io\/v1\r\ningestUrl: wss:\/\/gateway-predix-data-services.run.aws-usw02-pr.ice.predix.io\/v1\/stream\/messages\r\nzoneId: 1cb45004-46a9-424c-a723-1578437f5078\r\n\r\nsecurity.oauth2.client:\r\nclientId: demo-ts-client-id\r\nclientSecret: client@pass\r\naccessTokenUri: https:\/\/a4ba93c9-f73e-4f94-bc1b-24b738151a2b.predix-uaa.run.aws-usw02-pr.ice.predix.io\/oauth\/token\r\nuserAuthorizationUri: https:\/\/a4ba93c9-f73e-4f94-bc1b-24b738151a2b.predix-uaa.run.aws-usw02-pr.ice.predix.io\/oauth\/authorize\r\ntokenName: oauth_token<\/pre>\n<p>In the query controller, <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">Qualifier<\/code> must be added for specifying the correct instance of <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">RestTemplate<\/code> to be used for sending requests to the Time Series endpoint.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">@Autowired\r\n@Qualifier(&quot;restTemplate&quot;)\r\nprivate RestTemplate restTemplate;<\/pre>\n<p>In the WebSocket controller, the injected <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">OAuth2RestTemplate<\/code> is used to get the bearer token on the fly and add it as a header when connecting to the WebSocket endpoint.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">@Autowired\r\n@Qualifier(&quot;restTemplate&quot;)\r\nprivate OAuth2RestTemplate restTemplate;\r\n\r\nprivate String getAccessToken() {\r\n  return restTemplate.getAccessToken().getValue();\r\n}<\/pre>\n<p>That&#8217;s it.<\/p>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Running_the_application\"><\/span>Running the application<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>To start the application locally, use the following command.<\/p>\n<pre style=\"padding-left: 30px;\">mvn spring-boot:run<\/pre>\n<p><\/p>\n<p>To run it on Predix, add this configuration to <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">manifest.yml<\/code>.<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">---\r\napplications:\r\n  - name: demo-ts-app\r\n\tbuildpack: java_buildpack\r\n\tpath: target\/demo-ts-app.jar\r\n\tmemory: 512m<\/pre>\n<p><\/p>\n<p>Finally, you can run the application on Cloud Foundry using the following commands:<\/p>\n<pre style=\"padding-left: 30px;\">mvn clean package\r\ncf push<\/pre>\n<p><center><a href=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2019\/07\/predix-time-series-spring-boot-running-the-app.png\" target=\"_blank\" rel=\"noopener noreferrer\"><img decoding=\"async\" src=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2019\/07\/predix-time-series-spring-boot-running-the-app.png\" alt=\"predix-time-series-spring-boot-running-the-app\" width=\"640\" class=\"aligncenter size-full wp-image-45030\" \/><\/a><\/center><\/p>\n<p>The source code for this demo application can be found in <a href=\"https:\/\/github.com\/Altoros\/predix-timeseries-example\" target=\"_blank\" rel=\"noopener noreferrer\">this GitHub repository<\/a>. Visit the <a href=\"https:\/\/www.predix.io\/docs\/?r=91740#B5nM6Ba\" target=\"_blank\" rel=\"noopener noreferrer\">UAA documentation<\/a> for more on User Account and Authentication in Predix.<\/p>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Further_reading\"><\/span>Further reading<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<ul>\n<li><a href=\"https:\/\/www.altoros.com\/blog\/how-to-use-snap-packages-when-collecting-iot-data-with-predix-time-series\/\">How to Use Snap Packages when Collecting IoT Data with Predix Time Series<\/a><\/li>\n<li><a href=\"https:\/\/www.altoros.com\/blog\/collecting-time-series-data-with-predix-a-golang-api-wrapper-included\/\">Collecting Time-Series Data with Predix (a Golang API Wrapper Included)<\/a><\/li>\n<li><a href=\"https:\/\/www.altoros.com\/blog\/configuring-uaa-to-provide-a-single-entry-point-for-kubernetes-and-cloud-foundry\/\">Configuring UAA to Provide a Single Entry Point for Kubernetes and Cloud Foundry<\/a><\/li>\n<\/ul>\n<hr \/>\n<p><center><small>This post was written by Pavel Orda, edited by <a href=\"https:\/\/www.altoros.com\/blog\/author\/viktoryia-fedzkovich\/\">Victoria Fedzkovich<\/a> and <a href=\"https:\/\/www.altoros.com\/blog\/author\/alex\/\">Alex Khizhniak<\/a>.<\/small><\/center><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction to Time Series<\/p>\n<p>User Account and Authentication (UAA) is an identity management service in Cloud Foundry, used as an OAuth2 provider by the GE Predix platform. Being responsible for managing timed measurements, Time Series, in its turn, enables to efficiently and concurrently store data, as well as quickly retrieve it.<\/p>\n<p>The [&#8230;]<\/p>\n","protected":false},"author":24,"featured_media":45039,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"content-type":"","footnotes":"","_links_to":"","_links_to_target":""},"categories":[7],"tags":[873,117,647],"class_list":["post-45026","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-news-and-opinion","tag-cloud-native","tag-iot","tag-predix"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.6 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Using Time Series in a Spring Boot App on Predix | Altoros<\/title>\n<meta name=\"description\" content=\"Learn how to configure the Time Series and UAA services and use them in a Spring Boot app with two controllers for querying and ingesting data.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.altoros.com\/blog\/using-time-series-in-a-spring-boot-app-on-predix\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Using Time Series in a Spring Boot App on Predix | Altoros\" \/>\n<meta property=\"og:description\" content=\"Introduction to Time Series User Account and Authentication (UAA) is an identity management service in Cloud Foundry, used as an OAuth2 provider by the GE Predix platform. Being responsible for managing timed measurements, Time Series, in its turn, enables to efficiently and concurrently store data, as well as quickly retrieve it. The [...]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.altoros.com\/blog\/using-time-series-in-a-spring-boot-app-on-predix\/\" \/>\n<meta property=\"og:site_name\" content=\"Altoros\" \/>\n<meta property=\"article:published_time\" content=\"2016-06-29T13:02:25+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2019-07-09T15:12:30+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2016\/06\/Using-Time-Series-in-a-Spring-Boot-App-on-Predix.gif\" \/>\n\t<meta property=\"og:image:width\" content=\"640\" \/>\n\t<meta property=\"og:image:height\" content=\"599\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/gif\" \/>\n<meta name=\"author\" content=\"Victoria Fedzkovich\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Victoria Fedzkovich\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.altoros.com\/blog\/using-time-series-in-a-spring-boot-app-on-predix\/\",\"url\":\"https:\/\/www.altoros.com\/blog\/using-time-series-in-a-spring-boot-app-on-predix\/\",\"name\":\"Using Time Series in a Spring Boot App on Predix | Altoros\",\"isPartOf\":{\"@id\":\"https:\/\/www.altoros.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.altoros.com\/blog\/using-time-series-in-a-spring-boot-app-on-predix\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.altoros.com\/blog\/using-time-series-in-a-spring-boot-app-on-predix\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2016\/06\/Using-Time-Series-in-a-Spring-Boot-App-on-Predix.gif\",\"datePublished\":\"2016-06-29T13:02:25+00:00\",\"dateModified\":\"2019-07-09T15:12:30+00:00\",\"author\":{\"@id\":\"https:\/\/www.altoros.com\/blog\/#\/schema\/person\/c7b416b09612e334a4e0184568906c36\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.altoros.com\/blog\/using-time-series-in-a-spring-boot-app-on-predix\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.altoros.com\/blog\/using-time-series-in-a-spring-boot-app-on-predix\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.altoros.com\/blog\/using-time-series-in-a-spring-boot-app-on-predix\/#primaryimage\",\"url\":\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2016\/06\/Using-Time-Series-in-a-Spring-Boot-App-on-Predix.gif\",\"contentUrl\":\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2016\/06\/Using-Time-Series-in-a-Spring-Boot-App-on-Predix.gif\",\"width\":640,\"height\":599},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.altoros.com\/blog\/using-time-series-in-a-spring-boot-app-on-predix\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.altoros.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Using Time Series in a Spring Boot App on Predix\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.altoros.com\/blog\/#website\",\"url\":\"https:\/\/www.altoros.com\/blog\/\",\"name\":\"Altoros\",\"description\":\"Insight\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.altoros.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.altoros.com\/blog\/#\/schema\/person\/c7b416b09612e334a4e0184568906c36\",\"name\":\"Victoria Fedzkovich\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.altoros.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2016\/03\/author-v-f-150x150.jpg\",\"contentUrl\":\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2016\/03\/author-v-f-150x150.jpg\",\"caption\":\"Victoria Fedzkovich\"},\"description\":\"Victoria Fedzkovich strives for effective technical communication at Altoros. As a professional with 7+ years of experience in technical and scientific writing, she creates content for user guides, manuals, white papers, and technical overviews. Victoria is currently focused on the Cloud Foundry ecosystem and IoT solutions.\",\"url\":\"https:\/\/www.altoros.com\/blog\/author\/viktoryia-fedzkovich\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Using Time Series in a Spring Boot App on Predix | Altoros","description":"Learn how to configure the Time Series and UAA services and use them in a Spring Boot app with two controllers for querying and ingesting data.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.altoros.com\/blog\/using-time-series-in-a-spring-boot-app-on-predix\/","og_locale":"en_US","og_type":"article","og_title":"Using Time Series in a Spring Boot App on Predix | Altoros","og_description":"Introduction to Time Series User Account and Authentication (UAA) is an identity management service in Cloud Foundry, used as an OAuth2 provider by the GE Predix platform. Being responsible for managing timed measurements, Time Series, in its turn, enables to efficiently and concurrently store data, as well as quickly retrieve it. The [...]","og_url":"https:\/\/www.altoros.com\/blog\/using-time-series-in-a-spring-boot-app-on-predix\/","og_site_name":"Altoros","article_published_time":"2016-06-29T13:02:25+00:00","article_modified_time":"2019-07-09T15:12:30+00:00","og_image":[{"width":640,"height":599,"url":"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2016\/06\/Using-Time-Series-in-a-Spring-Boot-App-on-Predix.gif","type":"image\/gif"}],"author":"Victoria Fedzkovich","twitter_misc":{"Written by":"Victoria Fedzkovich","Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.altoros.com\/blog\/using-time-series-in-a-spring-boot-app-on-predix\/","url":"https:\/\/www.altoros.com\/blog\/using-time-series-in-a-spring-boot-app-on-predix\/","name":"Using Time Series in a Spring Boot App on Predix | Altoros","isPartOf":{"@id":"https:\/\/www.altoros.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.altoros.com\/blog\/using-time-series-in-a-spring-boot-app-on-predix\/#primaryimage"},"image":{"@id":"https:\/\/www.altoros.com\/blog\/using-time-series-in-a-spring-boot-app-on-predix\/#primaryimage"},"thumbnailUrl":"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2016\/06\/Using-Time-Series-in-a-Spring-Boot-App-on-Predix.gif","datePublished":"2016-06-29T13:02:25+00:00","dateModified":"2019-07-09T15:12:30+00:00","author":{"@id":"https:\/\/www.altoros.com\/blog\/#\/schema\/person\/c7b416b09612e334a4e0184568906c36"},"breadcrumb":{"@id":"https:\/\/www.altoros.com\/blog\/using-time-series-in-a-spring-boot-app-on-predix\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.altoros.com\/blog\/using-time-series-in-a-spring-boot-app-on-predix\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.altoros.com\/blog\/using-time-series-in-a-spring-boot-app-on-predix\/#primaryimage","url":"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2016\/06\/Using-Time-Series-in-a-Spring-Boot-App-on-Predix.gif","contentUrl":"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2016\/06\/Using-Time-Series-in-a-Spring-Boot-App-on-Predix.gif","width":640,"height":599},{"@type":"BreadcrumbList","@id":"https:\/\/www.altoros.com\/blog\/using-time-series-in-a-spring-boot-app-on-predix\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.altoros.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Using Time Series in a Spring Boot App on Predix"}]},{"@type":"WebSite","@id":"https:\/\/www.altoros.com\/blog\/#website","url":"https:\/\/www.altoros.com\/blog\/","name":"Altoros","description":"Insight","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.altoros.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.altoros.com\/blog\/#\/schema\/person\/c7b416b09612e334a4e0184568906c36","name":"Victoria Fedzkovich","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.altoros.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2016\/03\/author-v-f-150x150.jpg","contentUrl":"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2016\/03\/author-v-f-150x150.jpg","caption":"Victoria Fedzkovich"},"description":"Victoria Fedzkovich strives for effective technical communication at Altoros. As a professional with 7+ years of experience in technical and scientific writing, she creates content for user guides, manuals, white papers, and technical overviews. Victoria is currently focused on the Cloud Foundry ecosystem and IoT solutions.","url":"https:\/\/www.altoros.com\/blog\/author\/viktoryia-fedzkovich\/"}]}},"_links":{"self":[{"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/posts\/45026","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/users\/24"}],"replies":[{"embeddable":true,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/comments?post=45026"}],"version-history":[{"count":17,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/posts\/45026\/revisions"}],"predecessor-version":[{"id":45053,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/posts\/45026\/revisions\/45053"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/media\/45039"}],"wp:attachment":[{"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/media?parent=45026"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/categories?post=45026"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/tags?post=45026"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}