RSocket XML Config support

This commit is contained in:
Artem Bilan
2019-05-16 13:51:24 -04:00
committed by Gary Russell
parent 87169bc77a
commit bc9aa83aea
9 changed files with 537 additions and 12 deletions

View File

@@ -0,0 +1,59 @@
/*
* Copyright 2002-2019 the original author or authors.
*
* 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
*
* https://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 org.springframework.integration.rsocket.config;
import org.w3c.dom.Element;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.integration.config.xml.AbstractInboundGatewayParser;
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
import org.springframework.integration.rsocket.inbound.RSocketInboundGateway;
/**
* Parser for the <inbound-gateway/> element of the 'rsocket' namespace.
*
* @author Mark Fisher
* @author Gary Russell
*/
public class RSocketInboundGatewayParser extends AbstractInboundGatewayParser {
@Override
protected Class<?> getBeanClass(Element element) {
return RSocketInboundGateway.class;
}
@Override
protected boolean isEligibleAttribute(String attributeName) {
return !attributeName.equals("path")
&& !attributeName.equals("rsocket-strategies")
&& !attributeName.equals("rsocket-connector")
&& !attributeName.equals("request-element-type")
&& super.isEligibleAttribute(attributeName);
}
@Override
protected void doPostProcess(BeanDefinitionBuilder builder, Element element) {
builder.addConstructorArgValue(element.getAttribute("path"));
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "request-element-type",
"requestElementClass");
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "rsocket-strategies",
"rSocketStrategies");
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "rsocket-connector",
"RSocketConnector");
}
}

View File

@@ -28,7 +28,8 @@ import org.springframework.integration.config.xml.AbstractIntegrationNamespaceHa
public class RSocketNamespaceHandler extends AbstractIntegrationNamespaceHandler {
public void init() {
registerBeanDefinitionParser("inbound-gateway", new RSocketInboundGatewayParser());
registerBeanDefinitionParser("outbound-gateway", new RSocketOutboundGatewayParser());
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright 2019 the original author or authors.
*
* 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
*
* https://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 org.springframework.integration.rsocket.config;
import org.w3c.dom.Element;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.core.Conventions;
import org.springframework.integration.config.xml.AbstractConsumerEndpointParser;
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
import org.springframework.integration.rsocket.outbound.RSocketOutboundGateway;
/**
* Parser for the 'outbound-gateway' element of the rsocket namespace.
*
* @author Artem Bilan
*
* @since 5.2
*/
public class RSocketOutboundGatewayParser extends AbstractConsumerEndpointParser {
@Override
protected String getInputChannelAttributeName() {
return "request-channel";
}
@Override
protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(RSocketOutboundGateway.class);
BeanDefinition routeExpression =
IntegrationNamespaceUtils.createExpressionDefinitionFromValueOrExpression("route", "route-expression",
parserContext, element, true);
builder.addConstructorArgValue(routeExpression);
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "client-rsocket-connector",
"clientRSocketConnector");
populateValueOrExpressionIfAny(builder, element, parserContext, "command");
populateValueOrExpressionIfAny(builder, element, parserContext, "publisher-element-type");
populateValueOrExpressionIfAny(builder, element, parserContext, "expected-response-type");
return builder;
}
private static void populateValueOrExpressionIfAny(BeanDefinitionBuilder builder, Element element,
ParserContext parserContext, String valueAttributeName) {
String expressionAttributeName = valueAttributeName + "-expression";
BeanDefinition expression =
IntegrationNamespaceUtils.createExpressionDefinitionFromValueOrExpression(valueAttributeName,
expressionAttributeName, parserContext, element, false);
if (expression != null) {
builder.addPropertyValue(Conventions.attributeNameToPropertyName(expressionAttributeName), expression);
}
}
}

View File

@@ -94,7 +94,7 @@ public class RSocketInboundGateway extends MessagingGatewaySupport implements In
private ResolvableType requestElementType;
/**
* Instantiate based on the provided path patterns to map this endpoint for incoming RSocket requests.
* Instantiate based on the provided Ant-style path patterns to map this endpoint for incoming RSocket requests.
* @param path the mapping patterns to use.
*/
public RSocketInboundGateway(String... path) {

View File

@@ -1,21 +1,246 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.springframework.org/schema/integration/rsocket"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:tool="http://www.springframework.org/schema/tool"
xmlns:integration="http://www.springframework.org/schema/integration"
targetNamespace="http://www.springframework.org/schema/integration/rsocket"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:tool="http://www.springframework.org/schema/tool"
xmlns:integration="http://www.springframework.org/schema/integration"
targetNamespace="http://www.springframework.org/schema/integration/rsocket"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/beans"/>
<xsd:import namespace="http://www.springframework.org/schema/tool"/>
<xsd:import namespace="http://www.springframework.org/schema/integration"
schemaLocation="https://www.springframework.org/schema/integration/spring-integration-5.2.xsd"/>
schemaLocation="https://www.springframework.org/schema/integration/spring-integration-5.2.xsd"/>
<xsd:annotation>
<xsd:documentation><![CDATA[
Defines the configuration elements for Spring Integration's RSocket adapters.
]]></xsd:documentation>
<xsd:documentation>
Defines the configuration elements for Spring Integration's RSocket channel adapters.
</xsd:documentation>
</xsd:annotation>
<xsd:element name="inbound-gateway">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation>
Configures a Messaging Gateway Endpoint for the
'org.springframework.integration.rsocket.inbound.RSocketInboundGateway to receive RSocket
requests and produce RSocket responses.
</xsd:documentation>
</xsd:annotation>
<xsd:complexContent>
<xsd:extension base="gatewayType">
<xsd:attribute name="path" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation>
The comma separated Ant-style path patterns this endpoint is mapped onto.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="error-channel" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.messaging.MessageChannel"/>
</tool:annotation>
</xsd:appinfo>
<xsd:documentation>
If a downstream exception is thrown and an error-channel is specified,
the MessagingException will be sent to this channel. Otherwise, any such exception
will be propagated to the calling system.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="rsocket-strategies" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
An 'RSocketStrategies' bean reference for encoding/decoding requests/replies.
</xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type
type="org.springframework.messaging.rsocket.RSocketStrategies"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="rsocket-connector" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
An optional 'AbstractRSocketConnector' bean reference for endpoint mapping registration.
</xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type
type="org.springframework.integration.rsocket.AbstractRSocketConnector"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="request-element-type" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
A 'Class' for a request message payload type (plain or `Publisher` element).
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="outbound-gateway">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation>
Configures a Consumer Endpoint for the
'org.springframework.integration.rsocket.outbound.RSocketOutboundGateway' to send requests
over RSocket connections.
</xsd:documentation>
</xsd:annotation>
<xsd:complexContent>
<xsd:extension base="gatewayType">
<xsd:choice minOccurs="0" maxOccurs="2">
<xsd:element ref="integration:poller" minOccurs="0"/>
<xsd:element name="transactional" type="integration:transactionalType" minOccurs="0"/>
<xsd:element name="request-handler-advice-chain" type="integration:handlerAdviceChainType"
minOccurs="0"/>
</xsd:choice>
<xsd:attribute name="order">
<xsd:annotation>
<xsd:documentation>
Specifies the order for invocation when this endpoint is connected as a
subscriber to a SubscribableChannel.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="route" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
A 'route' for the target RSocket endpoint.
Mutually exclusive with 'route-expression'.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="route-expression" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
A SpEL expression to evaluate a 'route' for target RSocket endpoint at runtime
against request message.
Mutually exclusive with 'route'.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="command" default="requestResponse">
<xsd:annotation>
<xsd:documentation>
A 'Command' for RSocket request type.
Mutually exclusive with 'command-expression'.
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:union memberTypes="commandType xsd:string"/>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="command-expression" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
A SpEL expression to evaluate a 'command' for RSocket request type at runtime
against request message.
Mutually exclusive with 'command'.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="publisher-element-type" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
A 'Class' for a request message payload 'Publisher' type.
Mutually exclusive with 'publisher-element-type-expression'.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="publisher-element-type-expression" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
A SpEL expression to evaluate a 'Class' or 'ParameterizedTypeReference'
for a request message payload 'Publisher' type at runtime
against request message.
Mutually exclusive with 'publisher-element-type'.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="expected-response-type" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
A 'Class' for an RSocket response.
Mutually exclusive with 'expected-response-type-expression'.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="expected-response-type-expression" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
A SpEL expression to evaluate a 'Class' or 'ParameterizedTypeReference'
for for an RSocket response at runtime
against request message.
Mutually exclusive with 'expected-response-type'.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="client-rsocket-connector" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
A 'ClientRSocketConnector' for client side requests.
</xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type
type="org.springframework.integration.rsocket.ClientRSocketConnector"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="gatewayType">
<xsd:annotation>
<xsd:documentation>
Defines common configuration for gateway adapters.
</xsd:documentation>
</xsd:annotation>
<xsd:attribute name="id" type="xsd:string"/>
<xsd:attribute name="request-channel" type="xsd:string" use="required">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.messaging.MessageChannel"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="reply-channel" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.messaging.MessageChannel"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="request-timeout" type="xsd:string"/>
<xsd:attribute name="reply-timeout" type="xsd:string"/>
<xsd:attributeGroup ref="integration:smartLifeCycleAttributeGroup"/>
</xsd:complexType>
<xsd:simpleType name="commandType">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="fireAndForget"/>
<xsd:enumeration value="requestResponse"/>
<xsd:enumeration value="requestStreamOrChannel"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>