将数据从SOAP处理程序传递给webservice服务器类。

huangapple go评论67阅读模式
英文:

Pass data from a SOAP handler to a webservice server Class

问题

以下是您提供的代码翻译部分:

@Component
public class EndPointHandler implements SOAPHandler<SOAPMessageContext> {
    private List<String> ssoToken;
    private Map<String, List<String>> headers;

    @Override
    public boolean handleMessage(SOAPMessageContext context) {
        Boolean isResponse = (Boolean) context.get(SOAPMessageContext.MESSAGE_OUTBOUND_PROPERTY);
        if (!isResponse) {
            headers = ((Map<String, List<String>>) context.get(MessageContext.HTTP_REQUEST_HEADERS));
            if (headers != null) {
                if (!headers.get("SSOToken").get(0).isEmpty()) {
                    List<String> ssoToken = headers.get("SSOToken");
                    LOGGER.info(ssoToken.get(0));
                    this.ssoToken = ssoToken;
                } else {
                    LOGGER.error("SSO Token value cannot be empty");
                    return false;
                }
            }
        }
        return true;
    }

    public void setSSOToken() {
        headers.put("SSOToken", this.ssoToken);
    }
}
@Component
public class ConnectionManager {
    private static final Logger LOGGER = LoggerFactory.getLogger(ConnectionManager.class);

    @Autowired
    private EndPointHandler handler;

    private void establishConnection(String uri) throws FileNetIntegrationException {
        handler.ssoToken; //  --> I need SSO token here but the value is NULL;
    }
}
@Bean
public Endpoint endpoint(Bus bus) {
    EndpointImpl endpoint = new EndpointImpl(bus, changeServiceEndpoint);
    WebService ws = AnnotationUtils.findAnnotation(endpoint.getImplementorClass(), WebService.class);
    endpoint.setAddress("/" + ws.serviceName());
    endpoint.publish();
    SOAPBinding binding = (SOAPBinding) endpoint.getBinding();
    ArrayList<Handler> handlerChain = new ArrayList<>();
    handlerChain.add(new EndPointHandler());
    binding.setHandlerChain(handlerChain);
    return endpoint;
}
英文:

I have a Spring boot SOAP services with cxf, and my Consumers are passing me SSO token in http header.. I am able to retrieve the SSO token using JAX-WS handler. I am saving that SSO token into handler class level variable, and after control going through various classes it reaches to a point where I have to make a request to another service and have to pass the same SSO token, but in my Connection class the SSO token value is NULL.

@Component
public class EndPointHandler implements SOAPHandler&lt;SOAPMessageContext&gt; {
    private List&lt;String&gt; ssoToken;
    private Map&lt;String, List&lt;String&gt;&gt; headers;

    @Override
    public boolean handleMessage(SOAPMessageContext context) {
        Boolean isResponse = (Boolean) context.get(SOAPMessageContext.MESSAGE_OUTBOUND_PROPERTY);
        if (!isResponse) {
            headers = ((Map&lt;String, List&lt;String&gt;&gt;) context.get(MessageContext.HTTP_REQUEST_HEADERS));
            if (headers != null) {
                if (!headers.get(&quot;SSOToken&quot;).get(0).isEmpty()) {
                    List&lt;String&gt; ssoToken = headers.get(&quot;SSOToken&quot;);
                    LOGGER.info(ssoToken.get(0));
                    this.ssoToken = ssoToken;
                } else {
                    LOGGER.error(&quot;SSO Token value cannot be empty&quot;);
                    return false;
                }
            }
        }
        return true;
    }

    public void setSSOToken() {
        headers.put(&quot;SSOToken&quot;, this.ssoToken);
    }
}

In my Connection class I have to set this SSO token as a header and make a call to another service but SSO token value is NULL.

Connection Class:

@Component
public class ConnectionManager {
    private static final Logger LOGGER = LoggerFactory.getLogger(ConnectionManager.class);

    @Autowired
    private EndPointHandler handler;

    private void establishConnection(String uri) throws FileNetIntegrationException {
        handler.ssoToken; //  --&gt; I need SSO token here but the value is NULL;
    }
}

This is how I set the handler chain in my WebServiceConfig class:

@Bean
public Endpoint endpoint(Bus bus) {
    EndpointImpl endpoint = new EndpointImpl(bus, changeServiceEndpoint);
    WebService ws = AnnotationUtils.findAnnotation(endpoint.getImplementorClass(), WebService.class);
    endpoint.setAddress(&quot;/&quot; + ws.serviceName());
    endpoint.publish();
    SOAPBinding binding = (SOAPBinding) endpoint.getBinding();
    ArrayList&lt;Handler&gt; handlerChain = new ArrayList&lt;&gt;();
    handlerChain.add(new EndPointHandler());
    binding.setHandlerChain(handlerChain);
    return endpoint;
}

答案1

得分: 4

我认为,就在我发布了最后一段代码之后,我立刻找到了一个解决方案,当我注意到在将其添加到处理程序链时使用了 new EndPointHandler().. 我尝试使用 @Autowired,这对我起了作用。

英文:

I think, I got a solution right after posting the last piece of code here when I noticed that I used new EndPointHandler() while adding it into handler chain.. I tried using Autowired it and it worked for me.

答案2

得分: 2

<sub>*据我所知,`jax-ws`上下文和`spring-ws`上下文彼此不相交。因此,这不是一个解决方案,而是一个变通方法。作为另一种变通方法,您可以使用一些单例的[`synchronizedMap`][1],或者使用`jax-ws`的`Handler`将请求重定向到具有扩展API的另一个端点。*</sub>

---

### 使用JAX-WS处理程序访问SOAP消息的HTTP头

如果您为`JAX-WS`的`WebService`配置了[`SOAPHandler`][2],那么您可以访问HTTP头并将它们作为[`SOAPElement`][5]类型的字段传递到[`SOAPBody`][4]中,反之亦然。为此,您必须使用这些字段扩展消息POJO,并对其进行[`XmlElement`][6]注释。然后您可以从您的[`WebService`][3]中访问它们。

*注意:*如果您的动态生成的WSDL基于Java类,那么它也会发生变化。但无论如何,旧的请求和响应都会被接受,因为这些字段默认不是必需的。

---

**示例:** `UserService` - 输入消息有一个`String`类型的字段,输出消息有一个`int`类型的字段。让我们分别使用一个`String`类型的`ssoToken`字段扩展它们。我们将从传入消息的HTTP头中读取此令牌,并在传出消息的HTTP头中将其发送回去。

GetUserRequest.java:
```java
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType
@XmlRootElement(name = "getUserRequest")
public class GetUserRequest {
    @XmlElement
    protected String ssoToken;
    @XmlElement(required = true)
    protected String name;

    // getters + setters + constructor
}

GetUserResponse.java:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType
@XmlRootElement(name = "getUserResponse")
public class GetUserResponse {
    @XmlElement
    protected String ssoToken;
    @XmlElement(required = true)
    protected int age;

    // getters + setters + constructor
}

UserServiceHandler.java

public class UserServiceHandler implements SOAPHandler<SOAPMessageContext> {
    @Override
    public boolean handleMessage(SOAPMessageContext soapMessageContext) {
        Boolean isResponse =
                (Boolean) soapMessageContext
                        .get(SOAPMessageContext.MESSAGE_OUTBOUND_PROPERTY);
        if (!isResponse) {
            // 请求消息
            return processIncomingMessage(soapMessageContext);
        } else {
            // 响应消息
            return processOutgoingMessage(soapMessageContext);
        }
    }
}

processIncomingMessage:

@SuppressWarnings("unchecked")
private boolean processIncomingMessage(SOAPMessageContext soapMessageContext) {
    Map<String, List<String>> headers =
            ((Map<String, List<String>>) soapMessageContext
                    .get(MessageContext.HTTP_REQUEST_HEADERS));
    if (headers == null || headers.isEmpty()) {
        return false;
    }
    List<String> ssoTokens = headers.get("SSOToken");
    if (ssoTokens == null || ssoTokens.size() != 1) {
        return false;
    }
    String ssoToken = ssoTokens.get(0);
    if (ssoToken == null || ssoToken.isEmpty()) {
        return false;
    }
    try {
        Iterator<Node> iterator =
                soapMessageContext.getMessage().getSOAPBody().getChildElements();
        while (iterator.hasNext()) {
            Node element = iterator.next();
            if (element.getNodeName().contains("getUserRequest")) {
                ((SOAPElement) element)
                        .addChildElement("ssoToken", element.getPrefix())
                        .setTextContent(ssoToken);
            }
        }
    } catch (SOAPException e) {
        e.printStackTrace();
        return false;
    }
    return true;
}

processOutgoingMessage:

@SuppressWarnings("unchecked")
private boolean processOutgoingMessage(SOAPMessageContext soapMessageContext) {
    Map<String, List<String>> headers =
            ((Map<String, List<String>>) soapMessageContext
                    .get(MessageContext.HTTP_RESPONSE_HEADERS));
    if (headers == null || headers.isEmpty()) {
        soapMessageContext
                .put(MessageContext.HTTP_RESPONSE_HEADERS, new HashMap<>());
        headers = ((Map<String, List<String>>) soapMessageContext
                .get(MessageContext.HTTP_RESPONSE_HEADERS));
    }
    try {
        Iterator<Node> iterator = soapMessageContext
                .getMessage().getSOAPBody().getChildElements();
        while (iterator.hasNext()) {
            Node element = iterator.next();
            if (element.getNodeName().contains("getUserResponse")) {
                Iterator<Node> iteratorResponse =
                        ((SOAPElement) element).getChildElements();
                while (iteratorResponse.hasNext()) {
                    Node childElement = iteratorResponse.next();
                    if (childElement.getNodeName().contains("ssoToken")) {
                        String ssoToken = childElement.getTextContent();
                        headers.put("SSOToken",
                                Collections.singletonList(ssoToken));
                        element.removeChild(childElement);
                    }
                }
            }
        }
    } catch (SOAPException e) {
        e.printStackTrace();
        return false;
    }
    return true;
}

UserService.java

@WebService(endpointInterface = "com.example.UserPort",
        serviceName = "UserService")
@HandlerChain(file="handler-chain.xml")
public class UserService implements UserPort {
    public GetUserResponse getUser(GetUserRequest request) {
        GetUserResponse response = new GetUserResponse();
        response.setAge(23);
        response.setSsoToken(request.getSsoToken());
        return response;
    }
}

使用SoapUI进行测试:

请求头:

POST http://localhost:8080/ws/userService HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: text/xml;charset=UTF-8
SOAPAction: ""
SSOToken: 6cd506ac-738a-43ca-aee8-d13b78180605
Content-Length: 296
Host: localhost:8080
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)

请求消息:

<soapenv:Envelope
        xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
        xmlns:spr="http://example.com/jax-ws-sample">
    <soapenv:Header/>
    <soapenv:Body>
        <spr:getUserRequest>
            <spr:name>John</spr:name>
        </spr:getUserRequest>
    </soapenv:Body>
</soapenv:Envelope>

响应头:

HTTP/1.1 200 
SSOToken: 6cd506ac-738a-43ca-aee8-d13b78180605
Content-Type: text/xml;charset=utf-8
Transfer-Encoding:
<details>
<summary>英文:</summary>
&lt;sub&gt;*As far as I know, `jax-ws` context and `spring-ws` context don&#39;t intersect with each other. So this is not a solution but a workaround. As another workaround, you can use some singleton [`synchronizedMap`][1], or use a `jax-ws` `Handler` to redirect requests to another endpoint with extended api.*&lt;/sub&gt;
---
### Access HTTP headers of SOAP messages using JAX-WS handler
If you have configured [`SOAPHandler`][2] for your `JAX-WS` [`WebService`][3], then you can access the HTTP headers and pass them on inside the [`SOAPBody`][4] as fields of the [`SOAPElement`][5] type, and vice versa. To do this you have to extend the messages POJOs with these fields annotated as [`XmlElement`][6]. Then you can access them from your [`WebService`][3].
*Note:* If you have a dynamically generated WSDL schema based on Java classes, then it changes too. But anyway, the old requests and responses are accepted, because these fields are not required by default.
---
**Example:** `UserService` - the incoming message has one field of `String` type and outgoing message has one field of `int` type. Let&#39;s extend each of them with one `ssoToken` field of `String` type. We&#39;ll read this token from HTTP headers of incoming message and send it back in HTTP headers of outgoing message.
GetUserRequest.java:
```java
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType
@XmlRootElement(name = &quot;getUserRequest&quot;)
public class GetUserRequest {
@XmlElement
protected String ssoToken;
@XmlElement(required = true)
protected String name;
// getters + setters + constructor
}

GetUserResponse.java:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType
@XmlRootElement(name = &quot;getUserResponse&quot;)
public class GetUserResponse {
    @XmlElement
    protected String ssoToken;
    @XmlElement(required = true)
    protected int age;

    // getters + setters + constructor
}

UserServiceHandler.java

public class UserServiceHandler implements SOAPHandler&lt;SOAPMessageContext&gt; {
    @Override
    public boolean handleMessage(SOAPMessageContext soapMessageContext) {
        Boolean isResponse =
                (Boolean) soapMessageContext
                        .get(SOAPMessageContext.MESSAGE_OUTBOUND_PROPERTY);
        if (!isResponse) {
            // Request message
            return processIncomingMessage(soapMessageContext);
        } else {
            // Response message
            return processOutgoingMessage(soapMessageContext);
        }
    }
}

processIncomingMessage:

@SuppressWarnings(&quot;unchecked&quot;)
private boolean processIncomingMessage(SOAPMessageContext soapMessageContext) {
    Map&lt;String, List&lt;String&gt;&gt; headers =
            ((Map&lt;String, List&lt;String&gt;&gt;) soapMessageContext
                    .get(MessageContext.HTTP_REQUEST_HEADERS));
    if (headers == null || headers.isEmpty()) {
        return false;
    }
    List&lt;String&gt; ssoTokens = headers.get(&quot;SSOToken&quot;);
    if (ssoTokens == null || ssoTokens.size() != 1) {
        return false;
    }
    String ssoToken = ssoTokens.get(0);
    if (ssoToken == null || ssoToken.isEmpty()) {
        return false;
    }
    try {
        Iterator&lt;Node&gt; iterator =
                soapMessageContext.getMessage().getSOAPBody().getChildElements();
        while (iterator.hasNext()) {
            Node element = iterator.next();
            if (element.getNodeName().contains(&quot;getUserRequest&quot;)) {
                ((SOAPElement) element)
                        .addChildElement(&quot;ssoToken&quot;, element.getPrefix())
                        .setTextContent(ssoToken);
            }
        }
    } catch (SOAPException e) {
        e.printStackTrace();
        return false;
    }
    return true;
}

processOutgoingMessage:

@SuppressWarnings(&quot;unchecked&quot;)
private boolean processOutgoingMessage(SOAPMessageContext soapMessageContext) {
    Map&lt;String, List&lt;String&gt;&gt; headers =
            ((Map&lt;String, List&lt;String&gt;&gt;) soapMessageContext
                    .get(MessageContext.HTTP_RESPONSE_HEADERS));
    if (headers == null || headers.isEmpty()) {
        soapMessageContext
                .put(MessageContext.HTTP_RESPONSE_HEADERS, new HashMap&lt;&gt;());
        headers = ((Map&lt;String, List&lt;String&gt;&gt;) soapMessageContext
                .get(MessageContext.HTTP_RESPONSE_HEADERS));
    }
    try {
        Iterator&lt;Node&gt; iterator = soapMessageContext
                .getMessage().getSOAPBody().getChildElements();
        while (iterator.hasNext()) {
            Node element = iterator.next();
            if (element.getNodeName().contains(&quot;getUserResponse&quot;)) {
                Iterator&lt;Node&gt; iteratorResponse =
                        ((SOAPElement) element).getChildElements();
                while (iteratorResponse.hasNext()) {
                    Node childElement = iteratorResponse.next();
                    if (childElement.getNodeName().contains(&quot;ssoToken&quot;)) {
                        String ssoToken = childElement.getTextContent();
                        headers.put(&quot;SSOToken&quot;,
                                Collections.singletonList(ssoToken));
                        element.removeChild(childElement);
                    }
                }
            }
        }
    } catch (SOAPException e) {
        e.printStackTrace();
        return false;
    }
    return true;
}

UserService.java

@WebService(endpointInterface = &quot;com.example.UserPort&quot;,
        serviceName = &quot;UserService&quot;)
@HandlerChain(file=&quot;handler-chain.xml&quot;)
public class UserService implements UserPort {
    public GetUserResponse getUser(GetUserRequest request) {
        GetUserResponse response = new GetUserResponse();
        response.setAge(23);
        response.setSsoToken(request.getSsoToken());
        return response;
    }
}

Testing with SoapUI:

Request headers:

POST http://localhost:8080/ws/userService HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: text/xml;charset=UTF-8
SOAPAction: &quot;&quot;
SSOToken: 6cd506ac-738a-43ca-aee8-d13b78180605
Content-Length: 296
Host: localhost:8080
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)

Request message:

&lt;soapenv:Envelope
        xmlns:soapenv=&quot;http://schemas.xmlsoap.org/soap/envelope/&quot;
        xmlns:spr=&quot;http://example.com/jax-ws-sample&quot;&gt;
    &lt;soapenv:Header/&gt;
    &lt;soapenv:Body&gt;
        &lt;spr:getUserRequest&gt;
            &lt;spr:name&gt;John&lt;/spr:name&gt;
        &lt;/spr:getUserRequest&gt;
    &lt;/soapenv:Body&gt;
&lt;/soapenv:Envelope&gt;

Response headers:

HTTP/1.1 200 
SSOToken: 6cd506ac-738a-43ca-aee8-d13b78180605
Content-Type: text/xml;charset=utf-8
Transfer-Encoding: chunked
Date: Thu, 27 Aug 2020 15:54:33 GMT
Keep-Alive: timeout=20
Connection: keep-alive

Response message:

&lt;S:Envelope 
        xmlns:S=&quot;http://schemas.xmlsoap.org/soap/envelope/&quot;
        xmlns:SOAP-ENV=&quot;http://schemas.xmlsoap.org/soap/envelope/&quot;&gt;
    &lt;SOAP-ENV:Header/&gt;
    &lt;S:Body&gt;
        &lt;getUserResponse xmlns=&quot;http://example.com/jax-ws-sample&quot;&gt;
            &lt;age&gt;23&lt;/age&gt;
        &lt;/getUserResponse&gt;
    &lt;/S:Body&gt;
&lt;/S:Envelope&gt;

huangapple
  • 本文由 发表于 2020年8月22日 06:28:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/63530798.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定