Spring XD OAuth Sink 单元测试无法获取资源的新访问令牌 'null'
Spring XD OAuth Sink unit test Unable to obtain a new access token for resource 'null'
我正在尝试为我为 Spring XD 创建的接收器编写集成测试。这是我的 ModuleConfiguration.java
@Configuration
@EnableIntegration
public class ModuleConfiguration {
private OAuth2AccessToken token;
@Bean
public MessageChannel input() {
return new DirectChannel();
}
@Bean
protected OAuth2ProtectedResourceDetails resource() {
BaseOAuth2ProtectedResourceDetails resource = new BaseOAuth2ProtectedResourceDetails();
resource.setAccessTokenUri("https://xxxxxxxxxxx");
resource.setClientId("id");
resource.setClientSecret("secret");
resource.setGrantType("authorization_code");
return resource;
}
@Bean
public OAuth2RestTemplate oAuthTemplate() {
AccessTokenRequest atr = new DefaultAccessTokenRequest();
OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resource(), new DefaultOAuth2ClientContext(atr));
return restTemplate;
}
@Bean
public HeaderMapper<HttpHeaders> headerMapper() {
HeaderMapper<HttpHeaders> mapper = new DefaultHttpHeaderMapper();
HttpHeaders headers = new HttpHeaders();
token = oAuthTemplate().getAccessToken();
String authHeader = "Bearer " + token.getValue();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Authorization", authHeader);
mapper.toHeaders(headers);
return mapper;
}
@ServiceActivator(inputChannel="inputChannel")
@Bean
public MessageHandler httpout() {
HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler("https://yyyyyyyyy");
handler.setCharset("UTF-8");
handler.setHttpMethod(HttpMethod.POST);
handler.setHeaderMapper(headerMapper());
return handler;
}
}
我实现测试的方式与编写处理器测试的方式相同,并告诉 spring xd 这个模块是处理器,因为这是它所期望的。不确定,但我认为这不重要,我遇到的异常与 OAuth 有关。这里是SinkTest.java
public class SinkTest {
private static SingleNodeApplication application;
private static int RECEIVE_TIMEOUT = 5000;
private static String moduleName = "oauth-sink";
@BeforeClass
public static void setUp() {
application = new SingleNodeApplication().run();
SingleNodeIntegrationTestSupport singleNodeIntegrationTestSupport = new SingleNodeIntegrationTestSupport(
application);
singleNodeIntegrationTestSupport
.addModuleRegistry(new SingletonModuleRegistry(ModuleType.processor, moduleName));
}
@Test
public void test() {
String streamName = "sinkTest";
byte[] encoded = null;
String data = null;
try {
encoded = Files.readAllBytes(Paths.get("src/test/resources/dataunit.json"));
data = new String(encoded, "utf-8");
} catch (IOException e) {
e.printStackTrace();
fail("Exception thrown");
}
String processingChainUnderTest = moduleName;
SingleNodeProcessingChain chain = chain(application, streamName, processingChainUnderTest);
chain.sendPayload(data);
@SuppressWarnings("unchecked")
List<Map<String, Object>> result = (List<Map<String, Object>>) chain.receivePayload(RECEIVE_TIMEOUT);
// Unbind the source and sink channels from the message bus
chain.destroy();
// an exception is thrown by zookeeper when the spring xd container shuts down after the test passes
}
}
我的 ModuleConfiguration 的这一行出现异常
token = oAuthTemplate().getAccessToken();
Caused by: error="access_denied", error_description="Unable to obtain a new access token for resource 'null'. The provider manager is not configured to support it."
at org.springframework.security.oauth2.client.token.AccessTokenProviderChain.obtainNewAccessTokenInternal(AccessTokenProviderChain.java:146)
at org.springframework.security.oauth2.client.token.AccessTokenProviderChain.obtainAccessToken(AccessTokenProviderChain.java:118)
at org.springframework.security.oauth2.client.OAuth2RestTemplate.acquireAccessToken(OAuth2RestTemplate.java:221)
at org.springframework.security.oauth2.client.OAuth2RestTemplate.getAccessToken(OAuth2RestTemplate.java:173)
如果我像这样在 ModuleConfiguration 中使用 client_credentials 作为 GrantType
@Bean
protected OAuth2ProtectedResourceDetails resource() {
BaseOAuth2ProtectedResourceDetails resource = new ClientCredentialsResourceDetails();
resource.setAccessTokenUri("https://xxxxxxx");
resource.setClientId("id");
resource.setClientSecret("secret");
resource.setGrantType("client_credentials");
return resource;
}
我明白了
Caused by: org.springframework.integration.MessageDispatchingException: Dispatcher has no subscribers
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:107)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:97)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)
... 29 more
当我只有 clientId 和 secret 时,正确的授权类型是什么?我的 ModuleConfiguration 中是否缺少某些内容?
更新
我将 @ServiceActivator
中的 inputChannel 更改为正确的值,现在我得到了与之前 BaseOAuth2ProtectedResourceDetails
相同的异常。现在使用 ClientCredentialsResourceDetails
得到一个不同的异常
Caused by: java.lang.IllegalArgumentException: Map has no value for 'object-type'
at org.springframework.web.util.UriComponents$MapTemplateVariables.getValue(UriComponents.java:276)
at org.springframework.web.util.UriComponents.expandUriComponent(UriComponents.java:221)
at org.springframework.web.util.HierarchicalUriComponents$FullPathComponent.expand(HierarchicalUriComponents.java:650)
at org.springframework.web.util.HierarchicalUriComponents.expandInternal(HierarchicalUriComponents.java:319)
at org.springframework.web.util.HierarchicalUriComponents.expandInternal(HierarchicalUriComponents.java:46)
at org.springframework.web.util.UriComponents.expand(UriComponents.java:152)
at org.springframework.web.util.UriComponentsBuilder.buildAndExpand(UriComponentsBuilder.java:376)
at org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler.handleRequestMessage(HttpRequestExecutingMessageHandler.java:376)
... 35 more
首先尝试将 OAuthRestTemplate
注入 HttpExecutionMessageHandler
.
并且根本不要使用那个 headerMapper
,即使像豆子一样。在我看来,这正是我们拥有 OAuth RestTemplate
扩展的原因。
您的另一个问题是接收器及其 service-activator
的错误通道。对,那一定是 input
bean,但使用与 @ServiceActivator
相同的名称。这是你 Dispatcher has no subscribers
.
的根源
@ServiceActivator(inputChannel="inputChannel")
@Bean
public MessageHandler httpout() {
HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler("https://yyyyyyyyy", oAuthTemplate());
handler.setCharset("UTF-8");
handler.setHttpMethod(HttpMethod.POST);
return handler;
}
如果您在 URL 中有一些变量,例如 https://foo.bar/{foo}/{bar}
,您必须提供 setUriVariableExpressions(Map<String, Expression> uriVariableExpressions)
以在运行时针对 requestMessage
解析它们:http://docs.spring.io/spring-integration/reference/html/http.html#_mapping_uri_variables
我正在尝试为我为 Spring XD 创建的接收器编写集成测试。这是我的 ModuleConfiguration.java
@Configuration
@EnableIntegration
public class ModuleConfiguration {
private OAuth2AccessToken token;
@Bean
public MessageChannel input() {
return new DirectChannel();
}
@Bean
protected OAuth2ProtectedResourceDetails resource() {
BaseOAuth2ProtectedResourceDetails resource = new BaseOAuth2ProtectedResourceDetails();
resource.setAccessTokenUri("https://xxxxxxxxxxx");
resource.setClientId("id");
resource.setClientSecret("secret");
resource.setGrantType("authorization_code");
return resource;
}
@Bean
public OAuth2RestTemplate oAuthTemplate() {
AccessTokenRequest atr = new DefaultAccessTokenRequest();
OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resource(), new DefaultOAuth2ClientContext(atr));
return restTemplate;
}
@Bean
public HeaderMapper<HttpHeaders> headerMapper() {
HeaderMapper<HttpHeaders> mapper = new DefaultHttpHeaderMapper();
HttpHeaders headers = new HttpHeaders();
token = oAuthTemplate().getAccessToken();
String authHeader = "Bearer " + token.getValue();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Authorization", authHeader);
mapper.toHeaders(headers);
return mapper;
}
@ServiceActivator(inputChannel="inputChannel")
@Bean
public MessageHandler httpout() {
HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler("https://yyyyyyyyy");
handler.setCharset("UTF-8");
handler.setHttpMethod(HttpMethod.POST);
handler.setHeaderMapper(headerMapper());
return handler;
}
}
我实现测试的方式与编写处理器测试的方式相同,并告诉 spring xd 这个模块是处理器,因为这是它所期望的。不确定,但我认为这不重要,我遇到的异常与 OAuth 有关。这里是SinkTest.java
public class SinkTest {
private static SingleNodeApplication application;
private static int RECEIVE_TIMEOUT = 5000;
private static String moduleName = "oauth-sink";
@BeforeClass
public static void setUp() {
application = new SingleNodeApplication().run();
SingleNodeIntegrationTestSupport singleNodeIntegrationTestSupport = new SingleNodeIntegrationTestSupport(
application);
singleNodeIntegrationTestSupport
.addModuleRegistry(new SingletonModuleRegistry(ModuleType.processor, moduleName));
}
@Test
public void test() {
String streamName = "sinkTest";
byte[] encoded = null;
String data = null;
try {
encoded = Files.readAllBytes(Paths.get("src/test/resources/dataunit.json"));
data = new String(encoded, "utf-8");
} catch (IOException e) {
e.printStackTrace();
fail("Exception thrown");
}
String processingChainUnderTest = moduleName;
SingleNodeProcessingChain chain = chain(application, streamName, processingChainUnderTest);
chain.sendPayload(data);
@SuppressWarnings("unchecked")
List<Map<String, Object>> result = (List<Map<String, Object>>) chain.receivePayload(RECEIVE_TIMEOUT);
// Unbind the source and sink channels from the message bus
chain.destroy();
// an exception is thrown by zookeeper when the spring xd container shuts down after the test passes
}
}
我的 ModuleConfiguration 的这一行出现异常
token = oAuthTemplate().getAccessToken();
Caused by: error="access_denied", error_description="Unable to obtain a new access token for resource 'null'. The provider manager is not configured to support it."
at org.springframework.security.oauth2.client.token.AccessTokenProviderChain.obtainNewAccessTokenInternal(AccessTokenProviderChain.java:146)
at org.springframework.security.oauth2.client.token.AccessTokenProviderChain.obtainAccessToken(AccessTokenProviderChain.java:118)
at org.springframework.security.oauth2.client.OAuth2RestTemplate.acquireAccessToken(OAuth2RestTemplate.java:221)
at org.springframework.security.oauth2.client.OAuth2RestTemplate.getAccessToken(OAuth2RestTemplate.java:173)
如果我像这样在 ModuleConfiguration 中使用 client_credentials 作为 GrantType
@Bean
protected OAuth2ProtectedResourceDetails resource() {
BaseOAuth2ProtectedResourceDetails resource = new ClientCredentialsResourceDetails();
resource.setAccessTokenUri("https://xxxxxxx");
resource.setClientId("id");
resource.setClientSecret("secret");
resource.setGrantType("client_credentials");
return resource;
}
我明白了
Caused by: org.springframework.integration.MessageDispatchingException: Dispatcher has no subscribers
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:107)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:97)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)
... 29 more
当我只有 clientId 和 secret 时,正确的授权类型是什么?我的 ModuleConfiguration 中是否缺少某些内容?
更新
我将 @ServiceActivator
中的 inputChannel 更改为正确的值,现在我得到了与之前 BaseOAuth2ProtectedResourceDetails
相同的异常。现在使用 ClientCredentialsResourceDetails
Caused by: java.lang.IllegalArgumentException: Map has no value for 'object-type'
at org.springframework.web.util.UriComponents$MapTemplateVariables.getValue(UriComponents.java:276)
at org.springframework.web.util.UriComponents.expandUriComponent(UriComponents.java:221)
at org.springframework.web.util.HierarchicalUriComponents$FullPathComponent.expand(HierarchicalUriComponents.java:650)
at org.springframework.web.util.HierarchicalUriComponents.expandInternal(HierarchicalUriComponents.java:319)
at org.springframework.web.util.HierarchicalUriComponents.expandInternal(HierarchicalUriComponents.java:46)
at org.springframework.web.util.UriComponents.expand(UriComponents.java:152)
at org.springframework.web.util.UriComponentsBuilder.buildAndExpand(UriComponentsBuilder.java:376)
at org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler.handleRequestMessage(HttpRequestExecutingMessageHandler.java:376)
... 35 more
首先尝试将 OAuthRestTemplate
注入 HttpExecutionMessageHandler
.
并且根本不要使用那个 headerMapper
,即使像豆子一样。在我看来,这正是我们拥有 OAuth RestTemplate
扩展的原因。
您的另一个问题是接收器及其 service-activator
的错误通道。对,那一定是 input
bean,但使用与 @ServiceActivator
相同的名称。这是你 Dispatcher has no subscribers
.
@ServiceActivator(inputChannel="inputChannel")
@Bean
public MessageHandler httpout() {
HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler("https://yyyyyyyyy", oAuthTemplate());
handler.setCharset("UTF-8");
handler.setHttpMethod(HttpMethod.POST);
return handler;
}
如果您在 URL 中有一些变量,例如 https://foo.bar/{foo}/{bar}
,您必须提供 setUriVariableExpressions(Map<String, Expression> uriVariableExpressions)
以在运行时针对 requestMessage
解析它们:http://docs.spring.io/spring-integration/reference/html/http.html#_mapping_uri_variables