I have an application that is trying to access a webservice using generated classes via wsdl2java. I would like to be able to configure it so that I can use a different endpoint based on the environment (TEST/PROD).
I found the following answer to be exactly what I was looking for
https://stackoverflow.com/a/3569291/346666
However, I would like to use Spring to inject an instance of the service into my service layer - is there a pure Spring approach to the above?
Or, is there a better way to inject an instance of a webservice into a class and still be able to dynamically configure the endpoint?
Using Spring Java-based configuration:
#Configuration
public class HelloServiceConfig {
#Bean
#Scope("prototype")
public HelloService helloService(#Value("${webservice.endpoint.address}") String endpointAddress) {
HelloService service = new HelloService();
Hello port = service.getHelloPort();
BindingProvider bindingProvider = (BindingProvider) port;
bindingProvider.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,endpointAddress);
return service;
}
}
#Component
public class BusinessService {
#Autowired
private HelloService hellowService;
...
public void setHelloService(HelloService helloService) {
this.helloService = hellowService;
}
}
Edit
To use this with Spring XML-based configuration you just need to register the HelloServiceConfig as a bean in your Spring context xml file:
<bean class="com.service.HelloServiceConfig.class"/>
<bean id="businessService" class="com.service.BusinessService">
<property name="helloService" ref="helloService"/>
</bean>
Other alternatives for creating web service clients in Spring include using Spring Web Services or Apache CXF. Both options allow defining a JAX-WS client based on wsdl2java using only XML but required additional dependencies.
Related
With spring boot 2.6.0 (or above) is it possible to generate a rest client from a a controller interface?
Im wondering if its possible to build spring application like this following use case.
Spring application A needs to call spring application B rest interface
Spring application B is a multimodule project that produces server jar, and a api jar
Spring application A imports the B's API jar
Spring application A uses controller interface from B Api jar to make a rest client based on spring annotations.
B Api jar:
#RestsController
public interface MyApplicationAPI {
#GetMapping("/api/some-endpoint)
public SomeDto someEndpoint(SomeDTO obj);
}
B server jar:
public class BApplicationAPIImpl implements MyApplicationAPI {
public SomeDto someEndpoint(SomeDTO obj) {
return xxx;
And finally within A application:
MyApplicationAPI restClient = Some.magic(MyApplicationAPI.class, "http://bappurl.com")
SomeDto response = restClient.someEndpoint(param);
I believe that framework RestEasy supports similar approach, but you have to rely on JAXRS annotations.
Is there anything like that for spring framework? Or even better is there anything like this within spring already - i would prefer to rely on spring inhouse libraries and tools, rather than importing entire resteasy and jaxrs.
Spring Framework 6 (and Spring Boot 3) will have declarative HTTP interfaces (see documentation). However, they won't use the same annotations as controllers, but separate ones. So your example where you use the same interface for both controller and client won't be possible.
Code snippet from the documentation:
interface RepositoryService {
#GetExchange("/repos/{owner}/{repo}")
Repository getRepository(#PathVariable String owner, #PathVariable String repo);
// more HTTP exchange methods...
}
Initialization (the Some.magic() part in your question) can be done with WebClient. As can be seen in the same documentation:
WebClient client = WebClient.builder().baseUrl("https://api.github.com/").build();
HttpServiceProxyFactory factory = WebClientAdapter.createHttpServiceProxyFactory(client);
factory.afterPropertiesSet();
RepositoryService service = factory.createClient(RepositoryService.class);
I have read an article about mapping an DTO class to an entity. In the article, it manages to create a very general and extensible way of mapping DTO using annotations and RequestResponseBodyMethodProcessor. I have been creating a SOAP service using Spring Boot + Apache CXF. The service is still in an early stage, but it will get really big in the following months. The DTO pattern in the article seems to be a good choice for separating what the client sends and what is stored in the database. I have tried multiple ways of implementing it in the project, but none worked properly. I know RequestResponseBodyMethodProcessor is only used for #RequestBody and #ResponseBody, so I tried putting it in the SOAP Service, but Spring seems to ignore it completely. I have also done some search and maybe the problem comes from the fact CXF uses JAXB and Spring uses Jackson. If this is the case, is there any way to integrate CXF to use Jackson? If the problem isn't JAXB and Jackson, is there any other way of implementing the above pattern for a SOAP service? Just for completeness, the project is Java 1.8, the SOAP service is created using #WebService and the service is published through an WebServiceConfiguration class. Example code of how the code looks like:
#WebService
#Service
public interface MyService {
#WebMethod
public void myEndpoint(#WebParam(name = "someClass") SomeClass someClass);
// others endpoints
}
#Configuration
public interface WebServiceConfiguration {
#AutoWired
private MyServiceImpl myServiceImpl;
#Bean
public ServletRegistrationBean<CXFServlet> servletRegistrationBean(ApplicationContext context) {
return new ServletRegistrationBean<>(new CXFServlet(), "/service/*");
}
#Bean(name = Bus.DEFAULT_BUS_ID)
public SpringBus bus() {
return new SpringBus();
}
#Bean
public Endpoint myService() {
Edpoint endpoint = new EndpointImpl(bus(), myServiceImpl);
endpoint.publish("/myService");
return endpoint;
}
}
Can you help me convert following spring xml based configuration to java based configuration of beans?
<jaxws:client id="helloClient"
serviceClass="demo.spring.HelloWorld"
address="http://localhost:9002/HelloWorld" />
You just need to declare a bean in any of your configuration classes with the properties you have in your question.
It should look something like this:
#Bean(name = "helloClient") // this is the id
public HelloWorld helloWorld() {
String address = "http://localhost:9002/HelloWorld";
JaxWsProxyFactoryBean factoryBean = new JaxWsProxyFactoryBean();
factoryBean.setServiceClass(HelloWorld.class);
factoryBean.setAddress(address);
return (HelloWorld) factoryBean.create();
}
Your method will return an object of the Service class.
You need a Jax proxy factory bean to set the properties and then create the client (cast it to your service class) and return it.
I want to call a remote SOAP/CXF web service from a Spring app. The complication is I cannot pre-configure invocation params (remote endpoint URL) at app startup via XML or Java config. Instead I need to obtain them dynamically from an external configuration, taking a fresh value each invocation. (Actually the config is backed by LDAP and accessbible via a custom Java library.)
¿Does Spring 4 offers a common way to achieve that?
For now, I came with the following custom solution, but I don't like it much beacause I need to define a dummy proxy class DynamicallyConfiguredMyService at least.
#Component
class ParentBean {
#Inject
MyService service;
...
service.doAction(); // calling WS
}
interface MyService {
void doAction();
}
#Component
class DynamicallyConfiguredMyService implements MyService {
void doAction() {
getRealService.doAction();
}
private MyService getRealService() {
String url = get URL from external config
MyService endpoint = new MyServiceHelper().getMyService();
Map<String, Object> ctx = ((BindingProvider) endpoint).getRequestContext();
ctx.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, url);
return endpoint;
}
}
Spring 4, Java 7, JBoss EAP 6.4.x
I am new to Spring framework. Maybe this is more of a Java EE bean design question than related to Spring framework. Anyway, I just shoot it and see how clear I can make myself.
So I have a service. The service takes a connection string as constructor parameter. Then you can use the service to upload files to the location indicated by the connection string.
So you will start with something like:
public class MyService{
public MyService(String connectionStr){ ... }
}
When you need such a service, you call:
MyService service = new MyService("xxx");
...
That's what I used to do. Nothing fancy. Now if I do it in Java under Spring, I somehow want the service to be a bean. I need to do this:
#Component
public class MyService{
#Autowired
public MyService(#Value(...some connection string...) String connectionStr) {...}
}
But I get confused how you can inject dependency in compile time? I never know what connection string I will pass to create the service. When I read Spring tutorials, most of them have parameters coded in XML config file. Can I design a Spring bean like the one above but require the parameters to be passed in runtime?
Thanks.
You can design a method like this:
void upload(String location,XXX other parameters);
I didnt really get your question but will try to answer.
Check here or google to check if you really want to go for spring.
Coming to your query, For your service you would have to define some thing like this in your spring context.
<bean id="myService" class="com.blah.MyService">
<constructor-arg>
<value>http://HOST/test/</value>
</constructor-arg>
</bean>
Your service class will be,
public class MyService{
public MyService(String connectionString) {...}
}
This is how you will call your service in your application
ApplicationContext context = new ClassPathXmlApplicationContext(
new String[] { "context.xml" });
MyService service = (MyService) context
.getBean("myService");
The above can be implemented using annotations also. Check here for more details