Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using JaxWsPortProxyFactoryBean, or an equivalent, in Spring Boot 3?

I'm trying to upgrade a project that makes use of org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean in Spring Boot 2.7.5 to Spring Boot 3. Here's the declaration of my bean:

@Bean
public JaxWsPortProxyFactoryBean myJaxWsClient() {
    JaxWsPortProxyFactoryBean jaxWsPortProxyFactoryBean = new JaxWsPortProxyFactoryBean();
    jaxWsPortProxyFactoryBean.setJaxWsService(new My_Service());
    jaxWsPortProxyFactoryBean.setWsdlDocumentUrl(Thread.currentThread().getContextClassLoader().getResource("META-INF/my.wsdl"));
    jaxWsPortProxyFactoryBean.setNamespaceUri("urn:net:something");
    jaxWsPortProxyFactoryBean.setServiceName("MyService");
    jaxWsPortProxyFactoryBean.setServiceInterface(My.class);
    jaxWsPortProxyFactoryBean.setEndpointAddress("http://someuri:7979/myservice");
    jaxWsPortProxyFactoryBean.setUsername("username");
    jaxWsPortProxyFactoryBean.setPassword("password");
    return jaxWsPortProxyFactoryBean;
}

However, org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean doesn't seem to be available in Spring Boot 3, or it has moved to another library.

My question is: How do I use JaxWsPortProxyFactoryBean in Spring Boot 3, or how do I migrate to a more modern alternative (if available)?

like image 651
Johan Avatar asked Jan 31 '26 00:01

Johan


2 Answers

This class, as many others, has been removed in Spring Framework 6 (which is used by Spring Boot 3). It has been documented by this Github ticket and this commit. The old style remoting support (due to vulnerabilities and better options available) has been removed from the core library.

For the JAX-WS part you probably want to use something like Apache CXF in the current day and age, which would allow for a dynamic proxy. Another option is to implement the client yourself using Spring Web Services

like image 190
M. Deinum Avatar answered Feb 01 '26 15:02

M. Deinum


Jakarta JAXWS-RI is also an option: You generate MyService and MyPort using the jaxws-maven-plugin. Then you set it up using Spring, assuming you have written a MyConfigProperties class to access application.properties.

In a MyConfig class which sets up the beans and takes the MyConfigProperties, also adding SSL support for good measure:

@Configuration
public class MyConfig {

  public MyConfig(MyConfigProperties myConfigProperties) {
    this.myConfigProperties = myConfigProperties;
  }

  @Bean
  public MyService myService() {
    try {
        URL wsdlLocation = this.getClass().getResource("/META-INF/wsdl/my.wsdl");
        return new MyService(wsdlLocation); // may pass features here
    } catch (Exception e) {
        throw(new IllegalStateException(e);
    }
  }

  @Bean
  public KeyStoreFactoryBean keyStore() {
      KeyStoreFactoryBean keyStoreFactoryBean = new KeyStoreFactoryBean();
      Resource location = new ClassPathResource(myConfigProperties.getKeystoreLocation());
      keyStoreFactoryBean.setLocation(location);
      keyStoreFactoryBean.setPassword(myConfigProperties.getKeystorePassword());
      return keyStoreFactoryBean;
  }

  @Bean
  public KeyStoreFactoryBean trustStore() {
      KeyStoreFactoryBean keyStoreFactoryBean = new KeyStoreFactoryBean();
      Resource location = new ClassPathResource(myConfigProperties.getTruststoreLocation());
      keyStoreFactoryBean.setLocation(location);
      keyStoreFactoryBean.setPassword(myConfigProperties.getTruststorePassword());
      return keyStoreFactoryBean;
  }

  @Bean
  public TrustManagersFactoryBean trustManagers(KeyStore trustStore) {
      TrustManagersFactoryBean trustManagersFactoryBean = new TrustManagersFactoryBean();
      trustManagersFactoryBean.setKeyStore(trustStore);
      return trustManagersFactoryBean;
  }

  @Bean
  public KeyManagersFactoryBean keyManagers(KeyStore keyStore) {
      KeyManagersFactoryBean keyManagersFactoryBean = new KeyManagersFactoryBean();
      keyManagersFactoryBean.setKeyStore(keyStore);
      keyManagersFactoryBean.setPassword(props.getKeystorePassword());
      return keyManagersFactoryBean;
  }

  @Bean
  public SSLSocketFactory sslSocketFactory(TrustManager[] trustManagers, KeyManager[] keyManagers) throws Exception {
      SSLContext sslContext = SSLContext.getInstance("SSL");
      sslContext.init(keyManagers, trustManagers, new SecureRandom());
      return sslContext.getSocketFactory();
  }
}

In your client implementation:

@Component
public class MyClient {

  public MyClient(MyService myService, MyConfigProperties props,
      SSLSocketFactory sslSocketFactory) {
    this.myPort = myService.getMyPort();
    this.props = props;
    this.sslSocketFactory = sslSocketFactory;
  }

  public MyResult callEndpoint() {    
    BindingProvider bindingProvider = (BindingProvider) msgBoxPort;
    Map<String, Object> requestContext = bindingProvider.getRequestContext();
    requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, props.getWebserviceUri());
    requestContext.put(JAXWSProperties.SSL_SOCKET_FACTORY, sslSocketFactory);
    return myPort.callEndpoint();
  }
}

For the code generation you might be interested in https://stackoverflow.com/a/77465064/743507, I just recently went through the hassle to build a SOAP client for a rather complex WSDL, where I had to download a lot of schema files and needed a catalog to point the jaxws-maven-plugin to the downloaded stuff. This is generally a good idea, because you don't want your client to fail during startup if the target service is not available (or doesn't publish its WSDL properly).

like image 34
dschulten Avatar answered Feb 01 '26 15:02

dschulten



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!