diff --git a/.bumpversion.cfg b/.bumpversion.cfg index fa29a69..ced3638 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.1.0 +current_version = 0.2.0 commit = True tag = True diff --git a/README.md b/README.md index 4d3cf3f..be1c2f8 100644 --- a/README.md +++ b/README.md @@ -20,13 +20,13 @@ All you need to do is: com.ibm.watson.developer_cloud watson-spring-boot-starter - 0.1.0 + 0.2.0 ``` or in your gradle `build.gradle`, in the dependencies stanza, add ``` - compile 'com.ibm.watson.developer_cloud:watson-spring-boot-starter:0.1.0' + compile 'com.ibm.watson.developer_cloud:watson-spring-boot-starter:0.2.0' ``` 2. Add your Watson service(s) credentials and version info to your application @@ -36,7 +36,7 @@ use a different location. The properties to add are: - `watson..url`: The base URL for the service. This can be omitted if your service uses the default service url - - `watson..username` and `watson..password` OR `watson..apiKey`: + - `watson..username` and `watson..password` OR `watson..apiKey` OR `watson..iamApiKey`: The credentials for accessing the service. The credentials can be omitted from the application properties file if they are supplied through the `VCAP_SERVICES` environment variable. diff --git a/gradle.properties b/gradle.properties index 6b02f49..c010746 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ -version=0.1.0 +version=0.2.0 group = com.ibm.watson.developer_cloud -watsonVersion = 4.2.1 +watsonVersion = 6.1.0 springVersion = 4.3.12.RELEASE springBootVersion = 1.5.9.RELEASE diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 3bd3321..1948b90 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ac46377..d2c45a4 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Tue Jan 02 10:02:13 CST 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.8-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.0-bin.zip diff --git a/src/main/java/com/ibm/watson/developer_cloud/spring/boot/WatsonAssistantConfigurationProperties.java b/src/main/java/com/ibm/watson/developer_cloud/spring/boot/WatsonAssistantConfigurationProperties.java new file mode 100644 index 0000000..0deb705 --- /dev/null +++ b/src/main/java/com/ibm/watson/developer_cloud/spring/boot/WatsonAssistantConfigurationProperties.java @@ -0,0 +1,23 @@ +/* + * Copyright © 2017 IBM Corp. All rights reserved. + * + * Licensed 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. + */ + +package com.ibm.watson.developer_cloud.spring.boot; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties(prefix = WatsonAssistantConfigurationProperties.PREFIX) +public class WatsonAssistantConfigurationProperties extends WatsonConfigurationProperties { + + public static final String PREFIX = "watson.assistant"; +} diff --git a/src/main/java/com/ibm/watson/developer_cloud/spring/boot/WatsonAutoConfiguration.java b/src/main/java/com/ibm/watson/developer_cloud/spring/boot/WatsonAutoConfiguration.java index e2a0ec0..8d4abf0 100644 --- a/src/main/java/com/ibm/watson/developer_cloud/spring/boot/WatsonAutoConfiguration.java +++ b/src/main/java/com/ibm/watson/developer_cloud/spring/boot/WatsonAutoConfiguration.java @@ -14,13 +14,15 @@ package com.ibm.watson.developer_cloud.spring.boot; +import com.ibm.watson.developer_cloud.assistant.v1.Assistant; import com.ibm.watson.developer_cloud.conversation.v1.Conversation; import com.ibm.watson.developer_cloud.discovery.v1.Discovery; -import com.ibm.watson.developer_cloud.language_translator.v2.LanguageTranslator; +import com.ibm.watson.developer_cloud.language_translator.v3.LanguageTranslator; import com.ibm.watson.developer_cloud.natural_language_classifier.v1.NaturalLanguageClassifier; import com.ibm.watson.developer_cloud.natural_language_understanding.v1.NaturalLanguageUnderstanding; import com.ibm.watson.developer_cloud.personality_insights.v3.PersonalityInsights; import com.ibm.watson.developer_cloud.service.WatsonService; +import com.ibm.watson.developer_cloud.service.security.IamOptions; import com.ibm.watson.developer_cloud.speech_to_text.v1.SpeechToText; import com.ibm.watson.developer_cloud.text_to_speech.v1.TextToSpeech; import com.ibm.watson.developer_cloud.tone_analyzer.v3.ToneAnalyzer; @@ -34,6 +36,7 @@ @Configuration @EnableConfigurationProperties({ + WatsonAssistantConfigurationProperties.class, WatsonConversationConfigurationProperties.class, WatsonDiscoveryConfigurationProperties.class, WatsonLanguageTranslatorConfigurationProperties.class, @@ -54,21 +57,41 @@ private void configUrl(WatsonService service, WatsonConfigurationProperties conf } } - private void configBasicAuth(WatsonService service, WatsonConfigurationProperties config) { + private void configAuth(WatsonService service, WatsonConfigurationProperties config) { + String iamApiKey = config.getIamApiKey(); + if (iamApiKey != null) { + IamOptions options = new IamOptions.Builder().apiKey(iamApiKey).build(); + service.setIamCredentials(options); + return; + } String username = config.getUsername(); String password = config.getPassword(); if (username != null && password != null) { service.setUsernameAndPassword(username, password); + return; } - } - - private void configApiKey(WatsonService service, WatsonConfigurationProperties config) { String apiKey = config.getApiKey(); if (apiKey != null) { service.setApiKey(apiKey); + return; } } + // Watson Assistant service + + @Autowired + private WatsonAssistantConfigurationProperties assistantConfig; + + @Bean + @ConditionalOnMissingBean + @ConditionalOnWatsonServiceProperties(prefix = WatsonAssistantConfigurationProperties.PREFIX) + public Assistant assistant() { + Assistant service = new Assistant(assistantConfig.getVersionDate()); + configUrl(service, assistantConfig); + configAuth(service, assistantConfig); + return service; + } + // Watson Conversation service @Autowired @@ -80,7 +103,7 @@ private void configApiKey(WatsonService service, WatsonConfigurationProperties c public Conversation conversation() { Conversation service = new Conversation(conversationConfig.getVersionDate()); configUrl(service, conversationConfig); - configBasicAuth(service, conversationConfig); + configAuth(service, conversationConfig); return service; } @@ -95,7 +118,7 @@ public Conversation conversation() { public Discovery discovery() { Discovery service = new Discovery(discoveryConfig.getVersionDate()); configUrl(service, discoveryConfig); - configBasicAuth(service, discoveryConfig); + configAuth(service, discoveryConfig); return service; } @@ -108,9 +131,9 @@ public Discovery discovery() { @ConditionalOnMissingBean @ConditionalOnWatsonServiceProperties(prefix = WatsonLanguageTranslatorConfigurationProperties.PREFIX) public LanguageTranslator languageTranslator() { - LanguageTranslator service = new LanguageTranslator(); + LanguageTranslator service = new LanguageTranslator(ltConfig.getVersionDate()); configUrl(service, ltConfig); - configBasicAuth(service, ltConfig); + configAuth(service, ltConfig); return service; } @@ -125,7 +148,7 @@ public LanguageTranslator languageTranslator() { public NaturalLanguageClassifier naturalLanguageClassifier() { NaturalLanguageClassifier service = new NaturalLanguageClassifier(); configUrl(service, nlcConfig); - configBasicAuth(service, nlcConfig); + configAuth(service, nlcConfig); return service; } @@ -140,7 +163,7 @@ public NaturalLanguageClassifier naturalLanguageClassifier() { public NaturalLanguageUnderstanding naturalLanguageUnderstanding() { NaturalLanguageUnderstanding service = new NaturalLanguageUnderstanding(nluConfig.getVersionDate()); configUrl(service, nluConfig); - configBasicAuth(service, nluConfig); + configAuth(service, nluConfig); return service; } @@ -155,7 +178,7 @@ public NaturalLanguageUnderstanding naturalLanguageUnderstanding() { public PersonalityInsights personalityInsights() { PersonalityInsights service = new PersonalityInsights(piConfig.getVersionDate()); configUrl(service, piConfig); - configBasicAuth(service, piConfig); + configAuth(service, piConfig); return service; } @@ -170,7 +193,7 @@ public PersonalityInsights personalityInsights() { public SpeechToText speechToText() { SpeechToText service = new SpeechToText(); configUrl(service, sttConfig); - configBasicAuth(service, sttConfig); + configAuth(service, sttConfig); return service; } @@ -185,7 +208,7 @@ public SpeechToText speechToText() { public TextToSpeech textToSpeech() { TextToSpeech service = new TextToSpeech(); configUrl(service, ttsConfig); - configBasicAuth(service, ttsConfig); + configAuth(service, ttsConfig); return service; } @@ -200,7 +223,7 @@ public TextToSpeech textToSpeech() { public ToneAnalyzer toneAnalyzer() { ToneAnalyzer service = new ToneAnalyzer(taConfig.getVersionDate()); configUrl(service, taConfig); - configBasicAuth(service, taConfig); + configAuth(service, taConfig); return service; } @@ -215,8 +238,7 @@ public ToneAnalyzer toneAnalyzer() { public VisualRecognition visualRecognition() { VisualRecognition service = new VisualRecognition(vrConfig.getVersionDate()); configUrl(service, vrConfig); - configBasicAuth(service, vrConfig); - configApiKey(service, vrConfig); + configAuth(service, vrConfig); return service; } diff --git a/src/main/java/com/ibm/watson/developer_cloud/spring/boot/WatsonConfigurationProperties.java b/src/main/java/com/ibm/watson/developer_cloud/spring/boot/WatsonConfigurationProperties.java index 5951a82..61cc787 100644 --- a/src/main/java/com/ibm/watson/developer_cloud/spring/boot/WatsonConfigurationProperties.java +++ b/src/main/java/com/ibm/watson/developer_cloud/spring/boot/WatsonConfigurationProperties.java @@ -28,6 +28,9 @@ public class WatsonConfigurationProperties { /** Watson service API key. */ private String apiKey; + /** Watson service IAM API key. */ + private String iamApiKey; + /** Watson service versionDate. */ private String versionDate; @@ -47,6 +50,10 @@ public void setApiKey(String apiKey) { this.apiKey = apiKey; } + public void setIamApiKey(String apiKey) { + this.iamApiKey = apiKey; + } + public void setVersionDate(String versionDate) { this.versionDate = versionDate; } @@ -67,6 +74,10 @@ public String getApiKey() { return apiKey; } + public String getIamApiKey() { + return iamApiKey; + } + public String getVersionDate() { return this.versionDate; } diff --git a/src/main/java/com/ibm/watson/developer_cloud/spring/boot/WatsonServiceCondition.java b/src/main/java/com/ibm/watson/developer_cloud/spring/boot/WatsonServiceCondition.java index 68c74e1..735a9fa 100644 --- a/src/main/java/com/ibm/watson/developer_cloud/spring/boot/WatsonServiceCondition.java +++ b/src/main/java/com/ibm/watson/developer_cloud/spring/boot/WatsonServiceCondition.java @@ -23,8 +23,11 @@ public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata String url = conditionContext.getEnvironment().getProperty(prefix + ".url"); String username = conditionContext.getEnvironment().getProperty(prefix + ".username"); String password = conditionContext.getEnvironment().getProperty(prefix + ".password"); + String apiKey = conditionContext.getEnvironment().getProperty(prefix + ".apiKey"); + String iamApiKey = conditionContext.getEnvironment().getProperty(prefix + ".iamApiKey"); String versionDate = conditionContext.getEnvironment().getProperty(prefix + ".versionDate"); - if (url != null || username != null || password != null || versionDate != null) { + if (url != null || username != null || password != null || versionDate != null + || apiKey != null || iamApiKey != null) { return true; } diff --git a/src/test/java/com/ibm/watson/developer_cloud/spring/boot/test/AssistantAutoConfigTest.java b/src/test/java/com/ibm/watson/developer_cloud/spring/boot/test/AssistantAutoConfigTest.java new file mode 100644 index 0000000..5402522 --- /dev/null +++ b/src/test/java/com/ibm/watson/developer_cloud/spring/boot/test/AssistantAutoConfigTest.java @@ -0,0 +1,74 @@ +/* + * Copyright © 2017 IBM Corp. All rights reserved. + * + * Licensed 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. + */ + +package com.ibm.watson.developer_cloud.spring.boot.test; + +import com.ibm.watson.developer_cloud.assistant.v1.Assistant; +import com.ibm.watson.developer_cloud.service.WatsonService; +import com.ibm.watson.developer_cloud.spring.boot.WatsonAutoConfiguration; +import okhttp3.Credentials; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import java.lang.reflect.Field; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = {WatsonAutoConfiguration.class}, loader = AnnotationConfigContextLoader.class) +@TestPropertySource(properties = { + "watson.assistant.url=" + AssistantAutoConfigTest.url, + "watson.assistant.username=" + AssistantAutoConfigTest.username, + "watson.assistant.password=" + AssistantAutoConfigTest.password, + "watson.assistant.versionDate=" + AssistantAutoConfigTest.versionDate +}) +public class AssistantAutoConfigTest { + + static final String url = "http://watson.com/assistant"; + static final String username = "sam"; + static final String password = "secret"; + static final String versionDate = "2017-12-15"; + + @Autowired + private ApplicationContext applicationContext; + + @Test + public void assistantBeanConfig() { + Assistant assistant = (Assistant) applicationContext.getBean("assistant"); + + assertNotNull(assistant); + assertEquals(url, assistant.getEndPoint()); + + // Verify the credentials and versionDate -- which are stored in private member variables + try { + Field apiKeyField = WatsonService.class.getDeclaredField("apiKey"); + apiKeyField.setAccessible(true); + assertEquals(Credentials.basic(username, password), apiKeyField.get(assistant)); + + Field versionField = Assistant.class.getDeclaredField("versionDate"); + versionField.setAccessible(true); + assertEquals(versionDate, versionField.get(assistant)); + } catch (NoSuchFieldException | IllegalAccessException ex) { + // This shouldn't happen + assert false; + } + } +} diff --git a/src/test/java/com/ibm/watson/developer_cloud/spring/boot/test/AssistantIamAuthTest.java b/src/test/java/com/ibm/watson/developer_cloud/spring/boot/test/AssistantIamAuthTest.java new file mode 100644 index 0000000..2537157 --- /dev/null +++ b/src/test/java/com/ibm/watson/developer_cloud/spring/boot/test/AssistantIamAuthTest.java @@ -0,0 +1,75 @@ +/* + * Copyright © 2017 IBM Corp. All rights reserved. + * + * Licensed 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. + */ + +package com.ibm.watson.developer_cloud.spring.boot.test; + +import com.ibm.watson.developer_cloud.assistant.v1.Assistant; +import com.ibm.watson.developer_cloud.service.WatsonService; +import com.ibm.watson.developer_cloud.service.security.IamTokenManager; +import com.ibm.watson.developer_cloud.spring.boot.WatsonAutoConfiguration; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import java.lang.reflect.Field; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = {WatsonAutoConfiguration.class}, loader = AnnotationConfigContextLoader.class) +@TestPropertySource(properties = { + "watson.assistant.url=" + AssistantIamAuthTest.url, + "watson.assistant.iamApiKey=" + AssistantIamAuthTest.iamApiKey, + "watson.assistant.versionDate=" + AssistantIamAuthTest.versionDate +}) +public class AssistantIamAuthTest { + + static final String url = "http://watson.com/assistant"; + static final String iamApiKey = "super-secret-apikey"; + static final String versionDate = "2017-12-15"; + + @Autowired + private ApplicationContext applicationContext; + + @Test + public void assistantBeanConfig() { + Assistant assistant = (Assistant) applicationContext.getBean("assistant"); + + assertNotNull(assistant); + assertEquals(url, assistant.getEndPoint()); + + // Verify the credentials and versionDate -- which are stored in private member variables + try { + Field iamTokenManagerField = WatsonService.class.getDeclaredField("tokenManager"); + iamTokenManagerField.setAccessible(true); + IamTokenManager tokenManager = (IamTokenManager) iamTokenManagerField.get(assistant); + Field iamApiKeyField = IamTokenManager.class.getDeclaredField("apiKey"); + iamApiKeyField.setAccessible(true); + assertEquals(iamApiKey, iamApiKeyField.get(tokenManager)); + + Field versionField = Assistant.class.getDeclaredField("versionDate"); + versionField.setAccessible(true); + assertEquals(versionDate, versionField.get(assistant)); + } catch (NoSuchFieldException | IllegalAccessException ex) { + // This shouldn't happen + assert false; + } + } +} diff --git a/src/test/java/com/ibm/watson/developer_cloud/spring/boot/test/LanguageTranslatorAutoConfigTest.java b/src/test/java/com/ibm/watson/developer_cloud/spring/boot/test/LanguageTranslatorAutoConfigTest.java index 2d3d687..1d3be17 100644 --- a/src/test/java/com/ibm/watson/developer_cloud/spring/boot/test/LanguageTranslatorAutoConfigTest.java +++ b/src/test/java/com/ibm/watson/developer_cloud/spring/boot/test/LanguageTranslatorAutoConfigTest.java @@ -14,7 +14,7 @@ package com.ibm.watson.developer_cloud.spring.boot.test; -import com.ibm.watson.developer_cloud.language_translator.v2.LanguageTranslator; +import com.ibm.watson.developer_cloud.language_translator.v3.LanguageTranslator; import com.ibm.watson.developer_cloud.service.WatsonService; import com.ibm.watson.developer_cloud.spring.boot.WatsonAutoConfiguration; import okhttp3.Credentials; @@ -37,13 +37,15 @@ @TestPropertySource(properties = { "watson.language-translator.url=" + LanguageTranslatorAutoConfigTest.url, "watson.language-translator.username=" + LanguageTranslatorAutoConfigTest.username, - "watson.language-translator.password=" + LanguageTranslatorAutoConfigTest.password + "watson.language-translator.password=" + LanguageTranslatorAutoConfigTest.password, + "watson.language-translator.versionDate=" + LanguageTranslatorAutoConfigTest.versionDate }) public class LanguageTranslatorAutoConfigTest { static final String url = "http://watson.com/language-translator"; static final String username = "sam"; static final String password = "secret"; + static final String versionDate = "2018-06-12"; @Autowired private ApplicationContext applicationContext; diff --git a/src/test/java/com/ibm/watson/developer_cloud/spring/boot/test/WatsonAutoConfigTest.java b/src/test/java/com/ibm/watson/developer_cloud/spring/boot/test/WatsonAutoConfigTest.java index 4a8a77a..62b732c 100644 --- a/src/test/java/com/ibm/watson/developer_cloud/spring/boot/test/WatsonAutoConfigTest.java +++ b/src/test/java/com/ibm/watson/developer_cloud/spring/boot/test/WatsonAutoConfigTest.java @@ -14,7 +14,7 @@ package com.ibm.watson.developer_cloud.spring.boot.test; -import com.ibm.watson.developer_cloud.language_translator.v2.LanguageTranslator; +import com.ibm.watson.developer_cloud.speech_to_text.v1.SpeechToText; import com.ibm.watson.developer_cloud.service.WatsonService; import com.ibm.watson.developer_cloud.spring.boot.WatsonAutoConfiguration; import okhttp3.Credentials; @@ -36,10 +36,10 @@ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = {WatsonAutoConfiguration.class}, loader = AnnotationConfigContextLoader.class) -@TestPropertySource(properties = {"watson.language-translator.enabled=true"}) +@TestPropertySource(properties = {"watson.speech-to-text.enabled=true"}) public class WatsonAutoConfigTest { - private static final String url = "http://watson.com/language-translator"; + private static final String url = "http://watson.com/speech-to-text"; private static final String username = "sam"; private static final String password = "secret"; @@ -47,7 +47,7 @@ public class WatsonAutoConfigTest { public static final EnvironmentVariables environmentVariables = new EnvironmentVariables(); static { - String vcapServices = "{\"language_translator\":[{" + String vcapServices = "{\"speech_to_text\":[{" + "\"credentials\": {" + "\"url\":\"" + url + "\"," + "\"username\":\"" + username + "\"," @@ -63,17 +63,16 @@ public class WatsonAutoConfigTest { @Test public void watsonBeanConfigFromEnvironment() { - LanguageTranslator languageTranslator = (LanguageTranslator) applicationContext.getBean("languageTranslator"); + SpeechToText speechToText = (SpeechToText) applicationContext.getBean("speechToText"); - assertNotNull(languageTranslator); - // URL is not set from VCAP_SERVICES - //assertEquals(url, languageTranslator.getEndPoint()); + assertNotNull(speechToText); + assertEquals(url, speechToText.getEndPoint()); // Verify the credentials -- which are stored in a private member variable try { Field apiKeyField = WatsonService.class.getDeclaredField("apiKey"); apiKeyField.setAccessible(true); - assertEquals(Credentials.basic(username, password), apiKeyField.get(languageTranslator)); + assertEquals(Credentials.basic(username, password), apiKeyField.get(speechToText)); } catch (NoSuchFieldException | IllegalAccessException ex) { // This shouldn't happen assert false;