Spring framework web sockets unique #SendTo annotation - java

I have a web app that has registered users and i would like to push messages to users who have unique user ids. To be able to send a message to the clients, i need to know how to pass unique user id in the #sendto annotation
This is the annotation
#SendTo("/topic/uniqueuserid")
public Greeting greeting(HelloMessage message) throws Exception {
int uniqueuserid;
Thread.sleep(1000); // simulated delay
return new Greeting("Hello, " + message.getName() + uniqueuserid "!");
}
and this the stomp js
stompClient.subscribe('/topic/uniqueuserid', function (greeting) {
showGreeting(JSON.parse(greeting.body).content);
});
How can i pass a unique user id in #SendTo("/topic/uniqueuserid")

You can use #DestinationVariable annotation in a method argument, like that:
#MessageMapping("/mychat/{uniqueUserId}")
#SendTo("/topic/{uniqueUserId}")
public Message message(#DestinationVariable("uniqueUserId") Long uniqueUserId, HelloMessage message) {
logger.info("Unique user id: {}", uniqueUserId);
}

Related

How to get SessionId from Azure Service Bus Queue trigger in Azure Function using java?

I am trying to get SessionId, DeliveryCount from an Azure Service Bus Queue trigger in a Java Azure function. I am able to do this easily in a C# Function App. Somehow I found a way to get the Application Properties using binding. But unfortunately am unable to get the above mentioned properties. Any help is appreciated.
#FunctionName("ServiceBusQueueTriggerJava")
public void run(
#ServiceBusQueueTrigger(name = "message", queueName = "%ServiceBusQueue%", connection = "ServiceBusConnString", isSessionsEnabled = true) String message,
final ExecutionContext context, #BindingName("ApplicationProperties") Map<String, Object> properties) {
Logger log = context.getLogger();
log.info("Java Service Bus Queue trigger function executed.");
properties.entrySet().forEach(entry -> {
log.info(entry.getKey() + " : " + entry.getValue());
});
log.info(message);
}

Azure Queue trigger not working with Java

I have a spring boot application which will publish message on azure Queue. I have one more azure queueTrigger function written in Java which will listen to the same queue to which spring boot application has published a message. The queueTrigger function not able to detected messages published on queue.
Here is my publisher code
public static void addQueueMessage(String connectStr, String queueName, String message) {
try {
// Instantiate a QueueClient which will be
// used to create and manipulate the queue
QueueClient queueClient = new QueueClientBuilder()
.connectionString(connectStr)
.queueName(queueName)
.buildClient();
System.out.println("Adding message to the queue: " + message);
// Add a message to the queue
queueClient.sendMessage(message);
} catch (QueueStorageException e) {
// Output the exception message and stack trace
System.out.println(e.getMessage());
e.printStackTrace();
}
}
Here is my queueTrigger function app code
#FunctionName("queueprocessor")
public void run(
#QueueTrigger(name = "message",
queueName = "queuetest",
connection = "AzureWebJobsStorage") String message,
final ExecutionContext context
) {
context.getLogger().info(message);
}
I'm passing same connection-String and queueName, still doesn't work. If i run function on my local machine then it gets triggered but with error error image
As the official doc suggests,
Functions expect a base64 encoded string. Any adjustments to the encoding type (in order to prepare data as a base64 encoded string) need to be implemented in the calling service.
Update sender code to send base64 encoded message.
String encodedMsg = Base64.getEncoder().encodeToString(message.getBytes())
queueClient.sendMessage(encodedMsg);

How to make grpc StreamObserver object serializable in Java

I am using gprc bidirectional streaming for chat application in Spring boot and since StreamObserver<T> object is used to send message back from sever to client. So, I want to serialize StreamObserver<T> object and convert it into stream of bytes to store it in redis or some other database. But since, StreamObserver<T> is a interface which doesn't implement or extend serializable. So, I am looking for a solution to how to serialize it since there would be around thousands of user which be using the chat application and storing StreamObserver <T> in some Map<String, StreamObserver<T>> won't be good idea.
Currently, I am storing StreamObserver<T> objects in map.
Map<String, StreamObserver<T>>
Here, key of map is chat application's user's id and value of is StreamObserver object which contains onNext, onError, onCompleted functions to send message from server to client
// Storing StreamObserver object with user Id
public static Map<String, StreamObserver<Chat.ChatMessageFromServer>> observersMap = new HashMap<String, StreamObserver<Chat.ChatMessageFromServer>>();
#Override
public StreamObserver<Chat.ChatMessage> chat(final StreamObserver<Chat.ChatMessageFromServer> responseObserver) {
// responseObserver -> Storing it into a map. So, server could send message back to the client
String user = grpcServerInterceptor.contextKey.get();
System.out.println("");
System.out.println("User : " + user);
if (observersMap.get(user) == null) {
System.out.println("New User : " + user);
System.out.println("Adding User to observers map");
System.out.println("");
observersMap.put(user, responseObserver);
} else {
System.out.println("This User already exists in observersMap : " + user);
System.out.println("By the way, Updating it");
observersMap.put(user, responseObserver);
}
// This function sends message to client from Server
public void sendMessageFromServerToClient(String user, String message) {
// Fetching StreamObserver from observersMap as defined above
observersMap.get(user).onNext(Chat.ChatMessageFromServer.newBuilder().setMessage(Chat.ChatMessage.newBuilder().setTo(user).setFrom("Server").setMessage(message)).build());
System.out.println("Pushed message to user : " + user);
System.out.println("");
}
StreamObserver corresponds to a stream on a real TCP connection. That resource can't be transferred to a DB. There's no way to serialize it to a DB to reduce memory usage.

Spring framework for SAML - WebSSOProfileImpl

In the code below, can anyone tell me how the assertion consumer service is being derived, if I am not setting this value in my metadata.
What is happening now is that a user is entering a URL on the command line like:
http://test1:11100/blah/blah/login.jsp
The application redirects OK. But the saml request being generated has a completely different ACS, i.e...
AssertionConsumerServiceURL="http://test5:11101/blah/saml/SSO
This causes issues because the response has the wrong URL (should have the test1 one above).
It is not clear to me how the ip and port are derived, if I am not supplying this information in my code or configuration.
I basically want the request to have the IP/port that the user enters.
Thanks.
from: org.springframework.security.saml.websso.WebSSOProfileImpl.java
protected AssertionConsumerService getAssertionConsumerService(WebSSOProfileOptions options, IDPSSODescriptor idpSSODescriptor, SPSSODescriptor spDescriptor) throws MetadataProviderException {
List<AssertionConsumerService> services = spDescriptor.getAssertionConsumerServices();
// Use user preference
if (options.getAssertionConsumerIndex() != null) {
for (AssertionConsumerService service : services) {
if (options.getAssertionConsumerIndex().equals(service.getIndex())) {
if (!isEndpointSupported(service)) {
throw new MetadataProviderException("Endpoint designated by the value in the WebSSOProfileOptions is not supported by this profile");
} else {
log.debug("Using consumer service determined by user preference with binding {}", service.getBinding());
return service;
}
}
}
throw new MetadataProviderException("AssertionConsumerIndex " + options.getAssertionConsumerIndex() + " not found for spDescriptor " + spDescriptor);
}
// Use default
if (spDescriptor.getDefaultAssertionConsumerService() != null && isEndpointSupported(spDescriptor.getDefaultAssertionConsumerService())) {
AssertionConsumerService service = spDescriptor.getDefaultAssertionConsumerService();
log.debug("Using default consumer service with binding {}", service.getBinding());
return service;
}
// Iterate and find first match
if (services.size() > 0) {
for (AssertionConsumerService service : services) {
if (isEndpointSupported(service)) {
log.debug("Using first available consumer service with binding {}", service.getBinding());
return service;
}
}
}
throw new MetadataProviderException("Service provider has no assertion consumer service available for the selected profile " + spDescriptor);
}

JGroups on Receive ClassNotFoundException

So I am trying to send a message across the cluster, the message will contain a User object which is a Serializable class.
When I send a String or an int it works perfectly, the message is sent without a problem and all channels on the cluster receive it.
When I try to send my own object User it gives me this exception;
Dec 7, 2013 3:55:19 PM org.jgroups.logging.JDKLogImpl error
SEVERE: JGRP000019: failed passing message to receiver: %s
java.lang.IllegalArgumentException: java.lang.ClassNotFoundException: User
at org.jgroups.Message.getObject(Message.java:378)
at AuctionImpl$ReceiverClass.receive(AuctionImpl.java:151)
at org.jgroups.JChannel.up(JChannel.java:738)
This is my receive code;
public void receive(Message msg) {
User user = (User) msg.getObject();
System.out.println("Username: " + user.getUsername());
}
The odd thing is I can create a new instance of User inside the receive and get no problems. for example;
public void receive(Message msg) {
User user = new User("Test", "Test");
User user = (User) msg.getObject();
System.out.println("Username: " + user.getUsername());
}
Anyone got any ideas?
Take a look at the ClassNotFoundException: your User class is not on the classpath when running your program.

Categories