How to redirect websocket to restcontroller in spring web - spring-mvc

I have a MessageHandler to receive WebSocket message, and I want resend the message to some restcontrollers. Message has type and content fields, I want to treat them as PostMapping and RequestBody. Is this possible?
public class MessageHandler extends TextWebSocketHandler {
#Override
public void handleTextMessage(#Nonnull final WebSocketSession session, #Nonnull final TextMessage message) {
// parse message and send to restcontroller
}
}
public class WsMessage {
public int type;
public String content;
}

Related

How to show exception status code on error page use springmvc

Custom exception
public class JsonException extends RuntimeException{
private int code;
public JsonException() {
}
public JsonException(String message) {
super(message);
}
public JsonException(int code, String message) {
super(message);
this.code = code;
}
public JsonException(Throwable cause) {
super(cause);
}
public JsonException(String message, Throwable cause) {
super(message, cause);
}
}
Rest URI
#RestController
#RequestMapping("/api")
public class Rests {
#GetMapping("/e")
public Boolean exceptionCode() {
throw new JsonException(401, "test");
}}
Request for '/api/e', the error page write status 500.The problem is how to make the message is 'status=401,Type =test',
You are directly throwing exception in controller that why you got internal server error.
If you want return any specific reason then you have to construct object need to set the reason by exception.getMessage() and set the status code.

Springboot app ResponseBodyAdvice Not triggered

I am trying to update an audit entry using the response body advice but as far as I can tell it never gets executed. I see the bean in the logs:
{"timestamp":"2018-08-21T15:48:08.349Z","level":"INFO","thread":"main",
"logger":"org.springframework.data.rest.webmvc.RepositoryRestHandlerAdapter",
"message":"Detected ResponseBodyAdvice bean in responseAuditAdvice","context":"default"}
My controller method looks like this:
#PostMapping(path = "/stage", consumes = {
"application/json"
}, produces = {
"application/json"
})
#ResponseBody
public ResponseEntity<?> stage(#Valid #RequestBody StagingDto stagingDto,
#RequestHeader(HttpHeaders.USER_AGENT) String userAgent,
BindingResult bindingResult) {
I have a RequestAuditAdvice that extends RequestBodyAdviceAdapter and it is working fine. Also if the error flow occurs I see the exception advice executing as well. it is only the response advice that is failing to trigger. Any suggestions?
here is the advice bean:
#Slf4j
#RequiredArgsConstructor(onConstructor_ = #Inject)
#ControllerAdvice
public class ResponseAuditAdvice implements ResponseBodyAdvice<Object> {
private final RequestService requestService;
#Override
public boolean supports(MethodParameter returnType, Class converterType) {
return true;
}
#Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType,
ServerHttpRequest request, ServerHttpResponse response) {
log.info("Updating audit for response.");
String ip = new String (request.getRemoteAddress().getAddress().getAddress());
requestService.auditResponse(ip, 200);
return body;
}
}

Get HubContext from outside of Hub using Aspnetcore.signalr libray (not from Controller)

I am developing SignalR service using AspNetCore.SignalR.
Following is my Hub:
public class NotificationHub : Microsoft.AspNetCore.SignalR.Hub
{
public override async Task OnConnectedAsync()
{
await base.OnConnectedAsync();
}
public override async Task OnDisconnectedAsync(Exception exception)
{
await base.OnDisconnectedAsync(exception);
}
}
Following is Another Context class that i have created to invoke Hub's method on client side:
public class NotificationHubContext
{
private readonly IHubContext<NotificationHub> _context;
public NotificationHubContext(IHubContext<NotificationHub> context)
{
_context = context;
}
public async Task Broadcast(string groupId, string eventName, object data)
{
await _context.Clients.Group(groupId).SendAsync(eventName, data);
}
}
I would like to Inject reference of NotificationContext class into my own IoC Container so I can just resolve it and call a BroadCast method on it and it should handle sending messages to clients.
I am using Service Bus to listen for messages from another part of the system, once I receive a message from Queue, I would like to notify Connected clients using HubContext from QueueHandler.
Assembly Info
var hubContext = app.ApplicationServices.GetService<IHubContext<Notification>>
That resolved my issue.
I design my class as below.
public class NotificationHub : Microsoft.AspNetCore.SignalR.Hub
{
public static IHubContext<NotificationHub> Current { get; set; }
}
In your Startup class
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
NotificationHub.Current = app.ApplicationServices.GetService<IHubContext<NotificationFromServerHub>>();
}
So, you can use as like this from anywhere.
public class MyBizClass
{
public void DoSomething()
{
NotificationHub.Current.MyMethod(...);
}
}

CDI Interceptor not simultaneous to current request in servlet

Sorry for the title, i have no idea to get better title.
I create a simple servlet and implements CDI interceptor.
This is my servlet
#Inject
UserManagement user;
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
user.setUsername(request.getParameter("username"));
response.getWriter().println(user.getMessage());
}
This is UserManagement bean:
#SessionScoped
public class UserManagement implements Serializable{
private String username;
private String message = "";
#UsernameSet
public void setUsername(String username){
this.username = username;
}
}
This is interceptor binding (#UsernameSet):
#InterceptorBinding
#Inherited
#Target({ TYPE, METHOD })
#Retention(RUNTIME)
#Documented
public #interface UsernameSet {
}
This is the interceptor:
#UsernameSet
#Interceptor
public class UserInterceptor implements Serializable {
#Inject
UserManagement user;
#AroundInvoke
public Object aroundInvoke(InvocationContext ic) throws Exception {
LOGGER.info("Entering method: " + ic.getMethod().getName());
user.setMessage("Hello " + user.getUsername());
return ic.proceed();
}
}
The interceptor does work but the servlet return UserManagement bean from previous request, although the logger shows immediately.
example
First Request:
localhost?username=smitty
Browser screen:
Hello
Second Request:
localhost?username=werben
Browser screen:
Hello smitty
Third Request:
localhost?username=jensen
Browser screen:
Hello werben
When you create an interceptor, it's invoked either before or after your method is called. With the way you have written yours, it is invoked before your method is called. InvocationContext.proceed will effectively call your method (and other interceptors if others are wired in).
To get the behavior you're looking for, you can switch to this:
#UsernameSet
#Interceptor
public class UserInterceptor implements Serializable {
#Inject
UserManagement user;
#AroundInvoke
public Object aroundInvoke(InvocationContext ic) throws Exception {
LOGGER.info("Entering method: " + ic.getMethod().getName());
Object result = ic.proceed();
user.setMessage("Hello " + user.getUsername());
return result;
}
}

why customer converter do not work in spring mvc

Spring mvc controller
#RequestMapping(method = RequestMethod.GET)
public Result<String> create(Date beginDate) {
//...
}
client call this api, beginDate parameter used long type
curl 'http://localhost:8080/foos?beginDate=1459657565000'
the response is
>Error 400 Bad Request
maybe spring mvc cannot convert long to date automatically, so I wrote a customer converter
public class LongToDateConverter implements Converter<Long, Date> {
#Override
public Date convert(Long source) {
if (source == null ) {
return null;
}
return new Date(source);
}
}
#Configuration
#EnableWebMvc
public class WebMvcContext extends WebMvcConfigurerAdapter {
#Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new LongToDateConverter());
}
}
then I call this api again, still the same error
Error 400 Bad Request
and set breakpoint in convert method , and found it did not step into this method, So why this converter do not work?
Then I changed it to POST method
#RequestMapping(method = RequestMethod.POST)
public Result<String> create(CouponModel model) {
}
CouponModel:
private Date useBeginDate;
Still Error 400 Bad Request

Resources