Spring - How to stop and start a Webserice from web application? - java

I would like to create a functionality for the application admin to be able to stop and start the webservice from the front end without bringing down the entire application.
The application has various other interfaces, screens and jobs which need to run all the time. The webservice alone has to be shut down for some data maintenance work and needs to be up again after it is complete. The webservice is consumed by few thirdparty applications.
Application is built with Spring 3.0.5.
I need to somehow get the webservice object(?) in the controller and trigger stop/start.
spring-config.xml
<wss:binding url="/wss/shipRequest.wss">
<wss:service>
<ws:service bean="#shipRequestWS">
</ws:service>
</wss:service>
</wss:binding>
<bean id="shipRequestWS" class="com.xxx.ShipRequestService">
<property name="shipRequestBO" ref="shipRequestBO" />
</bean>
Service
#WebService
#SOAPBinding(style = SOAPBinding.Style.RPC, use = SOAPBinding.Use.LITERAL)
public interface ShipRequestService extends java.rmi.Remote {
WebService methods...
}

One of the most simple solutions will be adding a JMX controlled bean offering start and stop of the web service. This bean can implement the control in two types:
Setting a flag on the injected service. The service may throw an exception on deactivated state but needs to be extended to this special behavior.
The web service may be created by a special sub context to be loaded by the activation or stopped by deactivation. The context may be created with ClassPathXmlApplicationContext using the current context as a parent context.

For "lightweight" maintenance changes, you can simply make a check on a flag at the beginning of the service methods to know if you should process the request or not.This technique is widely used for feature flipping for example.

Related

Clean up method for spring boot application after request process

How to implement a clean up method after request finish process in a spring boot application for clean data such as thread locals
I try with ServletRequestListener.requestDestroyed api, but it does not get hit after the request finish
One possible answer is that you have neglected to register the listener. The Servlet javadocs say:
In order to receive these notification events, the implementation class must be either declared in the deployment descriptor of the web application, annotated with WebListener, or registered via one of the addListener methods defined on ServletContext.
There may be other ways to implement this using Spring; e.g. using a handler intercepter; see Remove ThreadLocal object within a Spring MVC website?
If you were using plain servlets (without the Spring MVC infrastructure), another approach would be to do the cleanup in your servlet's service method or the doXxx methods. Or in a Filter in front of the servlet.

Naming Spring Services when accessed by different client types

I am quite new to Spring and have a question related to Spring Service naming convention.
I have written a service, and used an annotation to define and name it.
#Service(value="CustomerService")
This service is implemented within a library that is used by a web app. Everything works fine and I can autowire my service into my client components.
Now I would also like to expose this service using http invoker. This works ok. I have define a /CustomerService http service which accesses CustomerService bean.
The issue I have is that one of my components, a client side component, that I used in my web app (CustomerDetailsValidator) can also be used in this new application.
In my CustomerDetailsValidator I have something like this:
#Autowired
#Qualifier(name="CustomerService").
But if I want to reuse my CustomerDetailsValidator and use it in my new app, this time I need to wire it to the httpservice instead.
Which means that the #Autowired and #Qualifier code is useless.
My question is what is the best practice in this case?
Should I still use #Service?
I guess I cannot use Qualifier anymore.
My feeling is that I should define everything in xml in each application context.
The web app using the library directly would just use the CustomerService bean as a singleton.
While my new client app would link the customer service id to the http service.
Is that a good approach? Do we have patterns for this?
Thanks and regards
Gilles

Inject a bean from another application context?

Is it possible to inject a bean from a web application that deploy in another server!
I declare a scenario to myself, I have two web application that use spring framework and deploy separately in different application servers (one is TOMCAT and another one is WEBLOGIC),the first application has ServiceA and the second one has ServiceB, now I want to inject ServiceB in ServieA?
I try to do this with RMI once an another one with JMS, now I am wondering that:
Is it possible with another thing?
Is there any active project about this scenario exist?
How can share application context in spring framework, is it possible?
Thanks.
Bean is just an object in JVM. You certainly cannot use an object from one JVM in another JVM straightforward.
But you can do 2 things:
Use proxies - some objects that will have the same interface but invoke somehow to the proper server as implementation.
Use service-oriented architecture (SOA). Each server should have some limited set of beans that are responsible for their functionality. And all beans can interact with each other.
Maybe OSGI is suitable for this.
Web services, JAX-RS is the simplest. But JAX-WS provides you with the tools to automatically generate the client code.

Dynamic Remote Service Location - How to inject with Spring?

I'm currently working on a distributed services architecture for a project at work. Essentially, we are managing upwards of 200 machines. Each of these machines has an instance of a service running on them that allows us to interface with the machine in a specific way.
At the center I have a control application which needs to talk to these 200 identical services. I was hoping to use RMI via Spring Remoting to make this happen, allowing me to #Autowire my remote service into my #Controller and treat it like a local service with exception propagation and maybe in the future propagation of transactions / security context via hooks.
This works great for a single service on a single machine where I can hardcode the remote service in my Spring configuration, but what I'm not able to figure out is how to dynamically choose which service (aka, which machine) I want to talk to at runtime and make that remote service available the "Spring" way.
I would like to be able to configure this dynamically from a database table and use the same table information to do a service lookup, while still taking advantage of dependency injection.
I thought of maybe injecting some kind of service manager that could do a service lookup of some sort, but was hoping someone else has managed to solve this (or a similar) problem elegantly.
An example of a hardcoded, single service instance would be like so:
The first XML snippet is on the machine service itself, telling Spring to expose it via RMI
<!-- Expose DeviceService via RMI -->
<bean class="org.springframework.remoting.rmi.RmiServiceExporter">
<property name="serviceName" value="DeviceService" />
<property name="service" ref="deviceService" />
<property name="serviceInterface"
value="com.example.service.DeviceService" />
<property name="registryPort" value="1199" />
</bean>
The second XML snippet is on the client (control application) which lets me access the exposed service
<!-- Proxy our remote DeviceService via RMI -->
<bean id="remoteDeviceService" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<property name="serviceUrl" value="rmi://machineurl:1199/DeviceService"/>
<property name="serviceInterface" value="com.example.service.DeviceService"/>
</bean>
It's that second bit of configuration that I'm trying to make dynamic. As you can see, to create this service proxy, I need to know at bean creation time the service URL. The Service URL can be 1 of 200+ variations, depending on what machine I want to talk to. The service I'm talking to is the same interface, but I won't know which machine until runtime depending on the current request context.
You could create connections to your servers dynamically with an additional service and remove "remoteDeviceService" from your client/controll app, i.e.:
public class RMIConnectionService {
public DeviceService connect(String serverUrl) {
RmiProxyFactoryBean factory = new RmiProxyFactoryBean();
factory.setServiceInterface(DeviceService.class);
factory.setServiceUrl("rmi://" + serverUrl + ":1099/SERVICE_URL");
factory.afterPropertiesSet();
//...
return (DeviceService) factory.getObject();
}
}
Then add this service to you service layer:
<bean id="rmiService" class="...RMIConnectionService" >
//...
</bean>
In your logic autowire the service and use it like:
DeviceService server1 = rmiService.connect("127.0.0.1");
For Database config add your DAO to this service, to load the right url. Port and url, or even the interface class could be configured this way too.
I have no RMI service to test this, but it worked with Hessian too. I hope this helps you.

should a Service layer be a Spring bean?

Can or should a Service layer be a Spring bean?
If so, how should it be got from a calling application, a consumer of a service?
Because the consumer must be aware that such a bean exists, so it in any case must use Spring
to make use of Service methods.
Of course. The service layer is the part of your application that is visible to other users (e.g. a Web layer) so it needs to be configured and setup somewhere. Imho a Spring configuration is the best place to put this configuration in. The Service Layer user then has to take care of instantiating that context and getting the Service Objects he needs.
An alternative - if it needs to run standalone - would be for your service class(es) implementing the Service Layer interface(s) to instantiate the Spring application context themselves.
By making your consumers also spring beans, and inject the service bean with dependency injection.
Yes, It is always nice to configure service beans as spring beans. In the web layer you need to take care of instantiating the needed service objects. Another option is to make the web layer classes also as spring beans and inject the necessary service layer spring beans. From the testing point of view also, this type of design is very helpful when we use Spring testing framework.

Categories

Resources