After seeing some examples at my class, I know that if I want to send a "TypeA" object to server and receive a "ProcessedA" object as a result, I only need one client class.
But if I want to send "TypeA", "TypeB", and "TypeC" objects (not at the same time) to server, do I need to make 3 different client classes, each one of which sends objects of one of those data types, or I only need to make one client class and write 3 different "send" methods?
You can have only one method if the objects you send inherits from one unique class or interface, and the same logic is applied to the result class.
It's a bit hard to understand what you need if you don't include a sample code of what you are trying (as is noticed in another post related to your request).
If this condition can be met by your needs, you can use the instanceof operator inside the server method to detect the type of the received object and cast it to the known child type. And apply the same logic to proccess the response in the client.
Related
I have a server that passes messages to a client. The messages are of different types and the server has a generic handleMessage and passMessage method for the clients.
Now I intend to adapt this and use GRPC for it. I know I could expose all methods of the server by defining services in my .proto file. But is there also a way to:
Stream
heterogenous types
with one RPC call
using GRPC
There is oneof which allows me to set a message that has only one of the properties set. I could have a MessageContainer that is oneof and all my message types are included in this container. Now the container only has one of the types and I would only need to write one
service {
rpc messageHandler(ClientInfo) returns (stream MessageContainer)
}
This way, the server could stream multiple types to the client through one unique interface. Does this make sense? Or is it better to have all methods exposed individually?
UPDATE
I found this thread which argues oneof would be the way to go. I'd like that obviously as it avoids me having to create potentially dozens of services and stubs. It would also help to make sure it's a FIFO setup instead of multiplexing several streams and not being sure which message came first. But it feels dirty for some reason.
Yes, this makes sense (and what you are calling MessageContainer is best understood as a sum type).
... but it is still better to define different methods when you can ("better" here means "more idiomatic, more readable by future maintainers of your system, and better able to be changed in the future when method semantics need to change").
The question of whether to express your service as a single RPC method returning a sum type or as multiple RPC methods comes down to whether or not the particular addend type that will be used can be known at RPC invocation time. Is it the case that when you set request.my_type_determining_field to 5 that the stream transmitted by the server always consists of MessageContainer messages that have their oneof set to a MyFifthKindOfParticularMessage instance? If so then you should probably just write a separate RPC method that returns a stream of MyFifthKindOfParticularMessage messages. If, however, it is the case that at RPC invocation time you don't know with certainty what the used addend types of the messages transmitted from the server will be (and "messages with different addend types in the same stream" is a sub-use-case of this), then I don't think it's possible for your service to be factored into different RPCs and the right thing for you to do is have one RPC method that returns a stream of a sum type.
I'm reading the two introductory articles about bulding and consuming Spring Rest web services.
What's weird - they're creating a Greeting representation class in the client app (second link ref) for storing the GET response (the greetingmethod on server side returns a Greeting object). But the Greeting classes on the server and client side are different classes - well, they are two distinct classes with identical names, identical field names and types (client's doesn't have a constructor).
Does it mean I have to similarly rewrite the class from stratch when building the client app? In order to do that, I'd need specs on what are the fields' types of JSON-packed objects passed by server's app. A server serializes the object of class ABCClass to JSON and sends it to client. Even if some field called 'abc' has value 10, it doesn't make it an integer. Next time it might contain a string.
My question is - how much information from server app's devs do I need in order to create a client application? How is it usually done?
It all depends on your deserializer and on your needs. With Jackson for example you might use mixins (wiki ref) and custom deserializers (wiki ref) that build your object with your required field names and your structure.
Its just simplest way to have same field names and structure, but not the only one.
Of course, however, you should know the server reply structure to deserialize it anyway
So I am working on this project, and I am having trouble on how to structure this. Basically, this is what I have:
Main Class instansiates Listener Class.
Listener class listens for packets.
When I packet is recieved, the Listener class creates a new instance of the Handler class (which is a runnable). The Handler class then reads the packet data and determines the packet type (reboot, shutdown, etc) and does what it needs with it.
What I want to do, is have a parent class Packet, and then have subclasses with all the different packet types RebootPacket, ShutdownPacket, etc.
I was going to just use tons of IF statements in the Handler class to create instances of the packet classes (if packetType = "reboot", RebootPacket packet = new RebootPacket) however, I feel that there should be a better way to do this. Could I some how use polymorphism to do this? Any suggestions are appreciated.
Here is my understanding of your problem, please correct me if I am wrong:
You are being fed data in "packets" which are really just Strings. These packets can have multiple types, and each type of packet has a different action associated with it. Each time a packet is read in, a new instance of the Handler class is created, which does what it needs to with the packet, depending on type. I am going to assume that the type of packet is inherent to the input.
In this case, I would suggest using polymorphism. I would create one method to do each of the 'actions' associated with individual types of packets. Each of these methods would have identical method signatures, except the parameter would be of a different type. For example:
public void doSomething(RebootPacket p)
and
public void doSomething(ShutDownPacket p)
This could be done for every packet type you will use. What this allows you to do is simply call doSomething(packet) and have it handle the packet in the correct way, regardless of type.
I suggest not using inheritance in this situation. When you have a subclass and a superclass, you want the subclass to have all or most of the same methods as the superclass, plus some of its own that the superclass cannot have. It seems to me like there aren't many methods which all of the packets would have in common, but rather a different way of handling each. If this is a correct assumption, polymorphism makes the most sense. If not, please comment with more information.
I have a multithread server, waiting for socket connections.
The first exchange of message is always of the same type, the clients sends an object with the authentication details(userid/pwd), the server checks it and reply to the server if the authentication has been passed or not.
After this first exchange of messages, the client will send some requests, corresponding to various tasks the server is able to execute.
How do i model those eterogeneous requests? In particular my question regards the type of object sent between client and server with InputObjecStream/OutputObjectStream
I had 2 ideas:
Using a "generic message" object, with 2 attributes: a task identifier and an HashMap without generics, able to carry various type of parameters requested for executing the task.
An object for every type of task, this solution is "cleaner", but I don't know how to make the server understand the type of the message received, I thought about a series of object casting of the received message from the client to every possible "specific task message", ignoring the many CastException. It sounds just bad, is there any way to avoid this?
Why not combine the two ideas
Start with a common level interface that the server can cast to determine what it should do or now to react.
As the object is passed off to the handler responsible for handling te request can further cast the object (based on a deeper level of interface implementation)
IMHO
The first approach is very generic but will be hard to maintain. After a while you'll notice that you no longer remember what kind of objects should be in this generic map. You'll have to keep the dictionary in sync.
The second approach is much better. Essentially you receive an abstract Request object with various subclasses. The base class can hold some general information. Normally you would use polymorphism and implement the action in each subclass, overriding abstract method from Request class. But you can't because request object would have to hold server-side logic.
The best you can do here is visitor design pattern. With it, for the price of slightly obscuring your code, you'll get very generic and safe design. instanceof tends to be ugly after some time.
What you could do is use XML messages for the communication. You could prepend in the first bytes an indication for which XML object the message should be mapped and on reception of the message, just check these bytes find the indicator, and use the rest bytesequence to marshal the bytes to XML object (using JAXB or SimpleXML or DOM or anyother xml parser) XML is very verbose and you could use it here to encapsulate your messages.
Im currently learning about RMI.
I dont really understand the concept of the codebase. Every paper i read suggests, that the client, which calls the Remote object can load the Method definitions from the codebase.
The Problem is now: Dont I need the descriptions/interfaces in my classpath anyway? How can i call methods on the remote object, if i only know them during Runtime? This Wouldnt even compile.
Am i completely missing the point here? What exactly is the point of the codebase then? It seems like a lot of extra work and requirements to provide a codebase
thanks
Well, let's say you provide to your client only interfaces, and the implementations will be located in a given code base. Then the client requests the server to send a given object, the client expects to receive an object that implements a given interface, but the actual implementation is unknown to the client, when it deserializes the sent object is when it has to go to the code base and download the corresponding implementing class for the actual object being passed.
This will make the client very thin, and you will very easily update your classes in the code base without having to resort to updating every single client.
EDIT
Let's say you have a RMI server with the following interface
public interface MiddleEarth {
public List<Creature> getAllCreatures();
}
The client will only have the interfaces for MiddleEarth and Creature, but none of the implementations in the class path.
Where the implementations of Creature are serializable objects of type Elf, Man, Dwarf and Hobbit. And these implementations are located in your code base, but not in your client's class path.
When you ask your RMI server to send you the list of all creatures in Middle Earth, it will send objects that implement Creature, that is, any of the classes listed above.
When the client receives the serialized objects it has to look for the class files in order to deserialized them, but these are not located in the local class path. Every object in this stream comes tagged with the given code base that can be used to look for missing classes. Therefore, the client resort to the code base to look for these classes. There it will find the actual creature classes being used.
The code base works in both directions, so it means that if you send your server a Creature (i.e. an Ent) it will look for it in the code base as well.
This means that when both, client and server need to publish new types of creatures all they have to do is to update the creaturesImpl.jar in the code base, and nothing in the server or client applications themselves.