I'm writing a library for my WebSocket (STOMP) on my webserver. I'm trying to make it so that the library will return the object specified in the Generics.
Add stomp client
public <T> void addStompClient(T t, String url, String subscription, StompMessageListener<T> listener) {
StompClient<T> sc = new StompClient<T>(t, URI.create(url));
StompConnectionListener scl = new StompConnectionListener() {
public void onConnecting() {}
public void onConnected() {
sc.subscribe(subscription, listener);
}
public void onDisconnected() {}
};
sc.setStompConnectionListener(scl);
sc.connect();
clients.add(sc);
}
StompMessageListener
@FunctionalInterface
public interface StompMessageListener<T> {
void onMessage(T test);
}
StompClient class method and variables
@Getter
private T t;
protected StompClient(T tclass, URI serverUri) {
super(serverUri);
t = tclass;
}
@SuppressWarnings("unchecked")
@Override
public void onMessage(String message) {
StompFrame stompFrame = StompFrame.fromString(message);
switch (stompFrame.getCommand()) {
case CONNECTED:
stompConnected = true;
if (stompConnectionListener != null) {
stompConnectionListener.onConnected();
}
break;
case MESSAGE:
Integer subscriptionId = Integer.valueOf(stompFrame.getHeaders().get(StompHeader.SUBSCRIPTION.toString()));
Class<T> tclass = (Class<T>) t.getClass();
T test = (T) new Gson().fromJson(stompFrame.getBody(), tclass);
StompSubscription<T> listener = (StompSubscription<T>) subscriptions.get(subscriptionId);
listener.getListener().onMessage(test);
break;
case DISCONNECT:
stompConnected = false;
if (stompConnectionListener != null) {
stompConnectionListener.onDisconnected();
}
break;
default:
break;
}
}
Calling:
clientManager.addStompClient(Category.class, "ws://localhost:8080/stomp-api/v1/hub", "/stomp-api/v1/listener/category/create", (category) -> {
Bukkit.getConsoleSender().sendMessage(category.getName());
});
But in doing this, I get a:
java.lang.UnsupportedOperationException: Attempted to deserialize a java.lang.Class. Forgot to register a type adapter?
Anyone know how to fix this? I tried to add the type adapter but couldn't figure out how to do it properly
CodePudding user response:
If anyone runs across this, here is how I solved this using the comment from
Alternately, you can use Jackson, which can deserialize from a Class. Here's an example. – Christopher Schneider
@Override
public void onMessage(String message) {
StompFrame stompFrame = StompFrame.fromString(message);
switch (stompFrame.getCommand()) {
case CONNECTED:
stompConnected = true;
if (stompConnectionListener != null) {
stompConnectionListener.onConnected();
}
break;
case MESSAGE:
Integer subscriptionId = Integer.valueOf(stompFrame.getHeaders().get(StompHeader.SUBSCRIPTION.toString()));
ObjectMapper objectMapper = new ObjectMapper(new Gson());
T t = objectMapper.readValue(stompFrame.getBody(), tclass);
StompSubscription<T> listener = (StompSubscription<T>) subscriptions.get(subscriptionId);
listener.getListener().onMessage(t);
break;
case DISCONNECT:
stompConnected = false;
if (stompConnectionListener != null) {
stompConnectionListener.onDisconnected();
}
break;
default:
break;
}
}
The ObjectMapper was put in place. tclass = Class. This allowed me to use Jackson and Generics to provide the Object that will be returning from the stomp listener