Hotswapping server runtime behavior dynamically from client - java

Say I've got a logging service deployed to some (jaxrs-compliant) container.
#Path("/logger")
public class LogService
{
#GET
#Path("/log")
public Response log(final String #QueryParam("msg") msg)
{
System.out.println(msg);
// ...
}
}
If I make the following request to the container hosting this service, I expect to see the output of my message to the container's stdout log:
GET <host>:<port>/logger/log?msg=foo
Now I'd like to change the implementation of this log message at runtime with behavior specified by some arbitrary client.
For example, say we had an interface:
public interface LoggerApi
{
void logMessage(final String msg);
}
and the service was redefined to use an implementation of this interface:
#Path("/logger")
public class LogService
{
public static LoggerApi LOGGER = new LoggerApi()
{
void logMessage(final String msg)
{
System.out.println(msg);
}
}
#GET
#Path("/log")
public Response log(final String #QueryParam("msg") msg)
{
LOGGER.logMessage(msg);
// ...
}
}
The question thus becomes, how can I hot swap the implementation of logger with a new implementation defined by some client external to the server.
My first instinct was that RMI and/or dynamic proxies could get me where I wanted to be, but I'm not soo sure with all the security policy madness.
Essentially what I want is the ability to do the following:
#Path("/config")
public class ConfigService
{
#POST
#Path("/loggerApi")
public Response setLoggerApi(final LoggerApi clientSuppliedLogger)
{
LogService.LOGGER = clientSuppliedLogger;
// ...
}
}
Thoughts?
(Oh and I know this poses a severe security risk and such a pattern ought never be used in production environments. My interest is in designing a mock service where the service's behavior and side effects can be defined by the integration tests calling the mock service)

Related

Dynamic target for declarative service in OSGI

Given a consumer which uses a service, how can this consumer select a specific provider dynamically using declarative service ?
Example
Service.java
public interface Service {
public void do();
}
Provider1.java
public class Provider1 implements Service {
#Override
public void do(){
//a way
}
}
Provider2.java
public class Provider2 implements Service {
#Override
public void do(){
//another way
}
}
Consumer.java
public class Consumer {
private Service myService;
protected void bindService(Service s){ // Actually it's Provider1
myService = s;
}
protected void unbindService(Service s){
myService = null;
}
public void useThisKindOfService(String s){
// Do something crazy
}
}
So, what I would like it's instead of "Do something crazy", to find a way to reconfigure the consumer in order to release Provider1 and ask for Provider2.
Is it possible ?
Update related to "Duplicate Question"
OSGI/Felix Declarative services: How to filter the services to be bound
In my context I cannot use the declarative target because the value of the target has to be know at build time, in my case the target could be defined by a user at runtime.
Components of Declarative Services can be configured via ConfigurationAdmin. By doing that, the configuration of the component can be changed at runtime.
You can also change the configuration of myService.target via ConfigurationAdmin at runtime. If you do that, another reference will be bound to your component.
If the policy of the reference of your component is dynamic, the new reference will be bound without reactivating your component.
For more information, see the Declarative Services chapter of the OSGi Compendium specification.

DropWizard/Jersey API Clients

DropWizard uses Jersey under the hood for REST. I am trying to figure out how to write a client for the RESTful endpoints my DropWizard app will expose.
For the sake of this example, let's say my DropWizard app has a CarResource, which exposes a few simple RESTful endpoints for CRUDding cars:
#Path("/cars")
public class CarResource extends Resource {
// CRUDs car instances to some database (DAO).
public CardDao carDao = new CarDao();
#POST
public Car createCar(String make, String model, String rgbColor) {
Car car = new Car(make, model, rgbColor);
carDao.saveCar(car);
return car;
}
#GET
#Path("/make/{make}")
public List<Car> getCarsByMake(String make) {
List<Car> cars = carDao.getCarsByMake(make);
return cars;
}
}
So I would imagine that a structured API client would be something like a CarServiceClient:
// Packaged up in a JAR library. Can be used by any Java executable to hit the Car Service
// endpoints.
public class CarServiceClient {
public HttpClient httpClient;
public Car createCar(String make, String model, String rgbColor) {
// Use 'httpClient' to make an HTTP POST to the /cars endpoint.
// Needs to deserialize JSON returned from server into a `Car` instance.
// But also needs to handle if the server threw a `WebApplicationException` or
// returned a NULL.
}
public List<Car> getCarsByMake(String make) {
// Use 'httpClient' to make an HTTP GET to the /cars/make/{make} endpoint.
// Needs to deserialize JSON returned from server into a list of `Car` instances.
// But also needs to handle if the server threw a `WebApplicationException` or
// returned a NULL.
}
}
But the only two official references to Drop Wizard clients I can find are totally contradictory to one another:
DropWizard recommended project structure - which claims I should put my client code in a car-client project under car.service.client package; but then...
DropWizard Client manual - which makes it seem like a "DropWizard Client" is meant for integrating my DropWizard app with other RESTful web services (thus acting as a middleman).
So I ask, what is the standard way of writing Java API clients for your DropWizard web services? Does DropWizard have a client-library I can utilize for this type of use case? Am I supposed to be implementing the client via some Jersey client API? Can someone add pseudo-code to my CarServiceClient so I can understand how this would work?
Here is a pattern you can use using the JAX-RS client.
To get the client:
javax.ws.rs.client.Client init(JerseyClientConfiguration config, Environment environment) {
return new JerseyClientBuilder(environment).using(config).build("my-client");
}
You can then make calls the following way:
javax.ws.rs.core.Response post = client
.target("http://...")
.request(MediaType.APPLICATION_JSON)
.header("key", value)
.accept(MediaType.APPLICATION_JSON)
.post(Entity.json(myObj));
Yes, what dropwizard-client provides is only to be used by the service itself, most likely to communicate other services. It doesn't provide anything for client applications directly.
It doesn't do much magic with HttpClients anyway. It simply configures the client according to the yml file, assigns the existing Jackson object mapper and validator to Jersey client, and I think reuses the thread pool of the application. You can check all that on https://github.com/dropwizard/dropwizard/blob/master/dropwizard-client/src/main/java/io/dropwizard/client/JerseyClientBuilder.java
I think I'd go about and structure my classes as you did using Jersey Client. Following is an abstract class I've been using for client services:
public abstract class HttpRemoteService {
private static final String AUTHORIZATION_HEADER = "Authorization";
private static final String TOKEN_PREFIX = "Bearer ";
private Client client;
protected HttpRemoteService(Client client) {
this.client = client;
}
protected abstract String getServiceUrl();
protected WebResource.Builder getSynchronousResource(String resourceUri) {
return client.resource(getServiceUrl() + resourceUri).type(MediaType.APPLICATION_JSON_TYPE);
}
protected WebResource.Builder getSynchronousResource(String resourceUri, String authToken) {
return getSynchronousResource(resourceUri).header(AUTHORIZATION_HEADER, TOKEN_PREFIX + authToken);
}
protected AsyncWebResource.Builder getAsynchronousResource(String resourceUri) {
return client.asyncResource(getServiceUrl() + resourceUri).type(MediaType.APPLICATION_JSON_TYPE);
}
protected AsyncWebResource.Builder getAsynchronousResource(String resourceUri, String authToken) {
return getAsynchronousResource(resourceUri).header(AUTHORIZATION_HEADER, TOKEN_PREFIX + authToken);
}
protected void isAlive() {
client.resource(getServiceUrl()).get(ClientResponse.class);
}
}
and here is how I make it concrete:
private class TestRemoteService extends HttpRemoteService {
protected TestRemoteService(Client client) {
super(client);
}
#Override
protected String getServiceUrl() {
return "http://localhost:8080";
}
public Future<TestDTO> get() {
return getAsynchronousResource("/get").get(TestDTO.class);
}
public void post(Object object) {
getSynchronousResource("/post").post(object);
}
public void unavailable() {
getSynchronousResource("/unavailable").get(Object.class);
}
public void authorize() {
getSynchronousResource("/authorize", "ma token").put();
}
}
if anyone is trying to use DW 0.8.2 when building a client, and you're getting the following error:
cannot access org.apache.http.config.Registry
class file for org.apache.http.config.Registry not found
at org.apache.maven.plugin.compiler.AbstractCompilerMojo.execute(AbstractCompilerMojo.java:858)
at org.apache.maven.plugin.compiler.CompilerMojo.execute(CompilerMojo.java:129)
at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:132)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:208)
... 19 more
update your dropwizard-client in your pom.xml from 0.8.2 to 0.8.4 and you should be good. I believe a jetty sub-dependency was updated which fixed it.
<dependency>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-client</artifactId>
<version>0.8.4</version>
<scope>compile</scope>
</dependency>
You can integrated with Spring Framework to implement

Java annotations and websocket - why are annotations used instead of traditional approach?

Please look at the code I posted below. FYI, this is from the Oracle website's websocket sample:
https://netbeans.org/kb/docs/javaee/maven-websocketapi.html
My question is, how does this work?! -- especially, the broadcastFigure function of MyWhiteboard. It is not a abstract function that is overridden and it is not "registered" with another class as in the traditional sense. The only way I see it is when the compiler sees the #OnMessage annotation, it goes and inserts the broadcastFigure call into the compiled code for when a new message is received. But before calling this function, it flows through the received data through the FigureDecoder class - based on this decoder being specified in the annotation #ServerEndpoint. Within broadcastFigure, when sendObject is called, the compiler inserts a reference to FigureEncoder - based on what's specified in the annotation #ServerEndpoint. Is this accurate?
If so, why did this implementation do things this way using annotations? Before looking at this, I would have expected there to be an abstract OnMessage function which needs to be overridden and explicit registration functions for Encoder and Decoder. Instead of such a "traditional" approach, why does the websocket implementation do it via annotations?
Thank you.
Mywhiteboard.java:
#ServerEndpoint(value = "/whiteboardendpoint", encoders = {FigureEncoder.class}, decoders = {FigureDecoder.class})
public class MyWhiteboard {
private static Set<Session> peers = Collections.synchronizedSet(new HashSet<Session>());
#OnMessage
public void broadcastFigure(Figure figure, Session session) throws IOException, EncodeException {
System.out.println("broadcastFigure: " + figure);
for (Session peer : peers) {
if (!peer.equals(session)) {
peer.getBasicRemote().sendObject(figure);
}
}
}
#OnError
public void onError(Throwable t) {
}
#OnClose
public void onClose(Session peer) {
peers.remove(peer);
}
#OnOpen
public void onOpen(Session peer) {
peers.add(peer);
}
}
FigureEncoder.java
public class FigureEncoder implements Encoder.Text<Figure> {
#Override
public String encode(Figure figure) throws EncodeException {
return figure.getJson().toString();
}
#Override
public void init(EndpointConfig config) {
System.out.println("init");
}
#Override
public void destroy() {
System.out.println("destroy");
}
}
FigureDecoder.java:
public class FigureDecoder implements Decoder.Text<Figure> {
#Override
public Figure decode(String string) throws DecodeException {
JsonObject jsonObject = Json.createReader(new StringReader(string)).readObject();
return new Figure(jsonObject);
}
#Override
public boolean willDecode(String string) {
try {
Json.createReader(new StringReader(string)).readObject();
return true;
} catch (JsonException ex) {
ex.printStackTrace();
return false;
}
}
#Override
public void init(EndpointConfig config) {
System.out.println("init");
}
#Override
public void destroy() {
System.out.println("destroy");
}
}
Annotations have their advantages and disadvantages, and there is a lot to say about choosing to create an annotation based API versus a (how you say) "traditional" API using interfaces. I won't go into that since you'll find plenty of wars online.
Used correctly, annotations provide better information about what a class/method's responsibility is. Many prefer annotations and as such they have become a trend and they are used everywhere.
With that out of the way, let's get back to your question:
Why did this implementation do things this way using annotations? Before looking at this, I would have expected there to be an abstract OnMessage function which needs to be overridden and explicit registration functions for Encoder and Decoder. Instead of such a "traditional" approach, why does the websocket implementation do it via annotations?
Actually they don't. Annotation is just a provided way of using the API. If you don't like it then you can do it the old way. Here is from the JSR-356 spec:
There are two main means by which an endpoint can be created. The first means is to implement certain of
the API classes from the Java WebSocket API with the required behavior to handle the endpoint lifecycle,
consume and send messages, publish itself, or connect to a peer. Often, this specification will refer to this
kind of endpoint as a programmatic endpoint. The second means is to decorate a Plain Old Java Object
(POJO) with certain of the annotations from the Java WebSocket API. The implementation then takes these
annotated classes and creates the appropriate objects at runtime to deploy the POJO as a websocket endpoint.
Often, this specification will refer to this kind of endpoint as an
annotated endpoint.
Again, people prefer using annotations and that's what you'll find most of tutorials using, but you can do without them if you want it bad enough.

Implement RPC with underlying request/response protocol (JSON-RPC on SIP)

Look at the following use case.
I have a client (Java) application, which wants to get/set the state of another, remote application (C). The communication between them is done via SIP, which is run in another thread.
The SIP interface can do the following:
sendMessage
onRequest
I have two ideas for the architecture:
RPC (JSON-RPC)
Define a class which does the marshalling/unmarshalling for JSONRPCRequests and JSONRPCResponse (http://software.dzhuvinov.com/json-rpc-2.0-base.html)
Define a Invoker class, which has something like a call(server, name, arguments) method.
In the Invoker class, the name and arguments are put into a JSONRPCRequest and sent via the SIP layer sendMessage
Now comes my problem. How do i actually get the right back to the caller? The control flow is now:
The onRequest method is called, but I do now know whether it is the answer to my previous call. What i do is putting all responses reaching my server into a Map, and just poll that list in the Invoker.
A rough sketch might be;
Invoker (provides API to client)
class Invoker {
private Channel channel;
public Invoker(Channel channel) { this.channel = channel; }
public Object call(String server, String name, Object .. args) {
JSONRPCRequest req = ...;
channel.sendMessage(server, req.toString());
while( ! channel.hasResponse(req.id()) {
Thread.sleep(42);
}
return channel.getResponse(req.id()).result();
}
}
Channel (interface to messenger):
class Channel {
private Map<Object, JSONRPCResponse> responses = new //;
private Sip sip = new Sip() {
public void onRequest(String msg) {
JSONRPCResponse response = JSONRPCResponse.parse(msg);
responses.put(msg.id(), response);
}
};
public void sendMessage(String server, String message) {
sip.sendMessage();
}
public boolean hasResponse onRequest(Object id) {
responses.hasKey(id);
}
public JSONRPCResponse getResponse(Object id) {
responses.get(id);
responses.delete(id);
}
}
SIP (messenger itself):
abstract class Sip {
public void sendMessage(String msg) {
// SIP magic
}
public abstract void onRequest(String msg);
}
Is there a better way to do that? My biggest problems/code smells are:
the blocking in Invoker
the protocol is in Invoker, maybe I want to switch marshalling to something else
the map as mean to get the correct response for a request
the SIP abstract method looks strange
No error handling
No timeout
Message Passing
Is there an easy way to get rid of RPC, and implement something like RPC with just message passing? Any hints for pattern are welcome. I do not need the code itself, I am totally fine with just architecture. I tried to google for message passing implementations, and how they actually change state with it, but I did not find anything useful. How to implement timeout/ error handling?
Any good books/literature on that topic is also welcome, as I never programmed such distributed stuff.
Any other ideas on which protocol to use inside SIP to change state is welcome, too, as RPC was my initial thought, and I did not find anything other useful.
The code will not compile, I guess, it was just to visualize my idea.
Define a service interface that has meaningful (for the us case) methods. Instead of using blocking calls, have the client supply a ResponseHandler that will be invoked when the operation is complete:
interface ResponseHandler {
void onComplete(Response response);
void onError(Throwable error);
}
interface SomeService {
void set(String attribute, Object value, ResponsHandler responseHandler);
void get(String attribute, ResponseHandler responseHandler);
}
The implementation of the Service interface can use any suitable protocol, but it has to correlate requests with responses in order to invoke the correct callbacks.

RPC call - static methods is not working

I am trying to define a static method in the service interface to make an rpc call. But it doesn't allow me to do so. here I am pasting my code
Client class
public void sendDomesticData(String product,String dma,String yrmnths,String dist,String metrics) {
String url = GWT.getModuleBaseURL() + "domesticservice";
domesticServiceAsync = (DomesticServiceAsync) GWT.create(DomesticService.class);
ServiceDefTarget endpoint = (ServiceDefTarget) domesticServiceAsync;
endpoint.setServiceEntryPoint(url);
domesticServiceAsync.sendDomesticData(product,dma,yrmnths,dist,metrics,new Domestichandler<Void>() );
}
public class Domestichandler<Void> implements AsyncCallback<Void> {
#Override
public void onFailure(Throwable caught) {
String error = caught.getMessage();
System.out.println(error);
}
public void onSuccess(Void result) {
System.out.println("perfect");
}
}
Service
public interface DomesticService extends RemoteService {
public void sendDomesticData(String product,String dma,String yrmnths,String dist,String metrics);
}
public interface DomesticServiceAsync {
void sendDomesticData(String product,String dma,String yrmnths,String dist,String metrics,AsyncCallback<Void> callback);
}
Server side -
public void sendDomesticData(String product, String dma, String yrmnths, String dist, String metrics) {
System.out.println(product);
}
Basically I am trying to send the values from the front interface to the server side and I don't want any return value. But the values passed to the server side should be stored globally in the server class so i can access those values in different method. I tried changing all the senddomestic values to static but it won't allow me to do so? why?
Because RemoteServiceServlet needs to invoke your service methods somehow and the implementation expects instance methods. But this shouldn't prevent you from assigning the method data to static fields. Just be aware of multi threading.
GWT always uses instance methods for RPC calls, static methods are not possible in this case.
What is important to understand about GWT is that any RemoteServiceServlet instances are created and maintained by the servlet container (e.g. Tomcat). The servlet container might create a number of servlet instances on startup (Tomcat creates 6 RemoteServiceServlet instances by default) and then uses load balancing to determine which servlet handles an RPC request at a particular point in time. Depending on settings of course, you have little control over which RemoteServiceServlet instance exactly will handle a specific RPC request.
Therefore, if you want to store information on the server side globally using RPC calls, the idea proposed by YuPPie to use static fields of your RemoteServiceServlet implementation is a BAD idea. You will have no idea which of the RemoteServiceServlet instances maintained by the server contains your static data, and any subsequent calls to retrieve the data will give erratic results.
You have a few options, though. Storing the information in a database (or something similar) is the most straightforward option, but from your post I'm guessing you want something simpler. A singleton class which holds your data is probably the way to go. A thread-safe example:
public class DataContainer
{
private static DataContainer _singleton;
private String _dataField1;
public static synchronized DataContainer getInstance()
{
if (_singleton == null)
_singleton = new DataContainer();
return _singleton;
}
public synchronized String getDataField1()
{
return _dataField1;
}
public synchronized void setDataField1(String dataField1)
{
_dataField1 = dataField1;
}
}
Then in the server side implementation of your RPC call you could do something like:
public void sendDomesticData(String product, String dma, String yrmnths, String dist, String metrics)
{
DataContainer.getInstance().setDataField1(product);
}
This way, if there are multiple servlet instances they will all share the singleton instance of DataContainer, thus giving you a place to store your data globally. I hope this will help you.

Categories

Resources