Broadcast to only one client with Atmosphere - java

How do I broadcast messages from only one client to another with Atmosphere (Meteor)?I have currently this implementation based on meteor tutorial
#Override
public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException {
Meteor.build(req).addListener(new AtmosphereResourceEventListenerAdapter());
}
#Override
public void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException {
String body = req.getReader().readLine().trim();
//some DAO lookups - here I would like to say I want to broadcast only to concrete client
BroadcasterFactory.getDefault().lookup(DefaultBroadcaster.class, "/*").broadcast(UserDAO.getInstance().getUser(name));
}

Here is the Atmosphere FAQ on their wiki: https://github.com/Atmosphere/atmosphere/wiki/Creating-private-channel-of-communication-between-Browsers

Another solution I believe : for adressing only one client, you don't need to broadcast, you may just do this:
try
{
r.getResponse().write(message);
}
catch(IllegalStateException e)
{
logger.error("Could not send message through atmosphere " + userId);
}
where r is the resource that you can memorize in your program.

BroadcasterFactory.getDefault().lookup(atmosphereResource.uuid()).broadcast('something');

Related

Adding separate custom Servlet in Vaadin 23 - Spring 2.7.1

This question was already asked, however since then all answers (that I could found) are no longer valid.
Essentially I want to implement a website with Vaadin (V23), that communicates with a WebApp via POST requests that is running on another server (physically). To do it, I want to create separate Servlet that would handle the communication (receiving side) with another Server. Let's say, this is not implemneted version:
#WebServlet(urlPatterns = "/communication", name = "QuizServlet", asyncSupported = true)
public class QuizServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.sendError(400, "Not implemented");
}
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.sendError(400, "Not implemented");
}
}
The problem is however, that I always get redirected to default dispatcher Servlet, and it seems, regardless of what I do:
SpringVaadinServlet was deprecated and no longer exists, extending VaadinServlet does not work.
Changing mappings in properties (vaadin.url-mapping=) also does not work, I just get redirected to this new mapping in all cases.
Trying to do servlets on separate ports yields same redirection on all ports, even if explicitly registering my custom Servlet on the Connector, with separate Sevice (WebMvcConfigurer Tomcat configuration). Answer from this post, also too old.
Registering servlet directly also does not do anything (by implementing WebApplicationInitializer).
There for the question, how to make use of two different servlets with new Vaadin 23 and Spring Boot 2.7.1?
I have found some kind of a solution to my problem. Namely on startup of my BootAplication, I am also starting the second separate Tomcat server that uses my custom Servlet :
#Service
public class QuizServer {
private final Log log = LogFactory.getLog(QuizServer.class);
#PostConstruct
public void startServer() throws IOException, LifecycleException {
start();
}
private void start() throws IOException, LifecycleException {
Tomcat tomcat = new Tomcat();
String contextPath = "/";
String appBase = new File(".").getAbsolutePath();
Context ctx = tomcat.addContext(contextPath, appBase);
Tomcat.addServlet(ctx, "quizServlet", new QuizServlet());
ctx.addServletMappingDecoded("/*", "quizServlet");
tomcat.setPort(8085);
tomcat.start();
tomcat.getConnector();
log.info("Quiz server started");
}
}
#WebServlet(urlPatterns = "/*", name = "quizServlet", asyncSupported = true)
public class QuizServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().println("Test");
}
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.sendError(400, "Not implemented");
}
}
It is a bit crude though, since ideally, it shouldn't require a separate server.

Java - Token flow OAuth 2 E2E with code

I'm New to security & JAVA and I need to implement token follow of OAuth2, this is the exact flow which I need to implement (if there is some library which can help it's great )
http://tutorials.jenkov.com/oauth2/authorization-code-request-response.html
How can I achieve it with JAVA, I want to use some library that provide this functionality. the token flow should be against the UAA but any other similar example will be very helpful.
i've found this example but not sure how to use/test it E2E with UAA
Postman will be very helpful to simulate it...
https://developers.google.com/api-client-library/java/google-oauth-java-client/oauth2
UAA context
https://github.com/cloudfoundry/uaa
I would suggest you Spring as the most popular framework for building web apps in Java. It has Spring Security module that can facilitate developing OAuth 2.0 clients as well as resource servers, as shown here or here.
For a detailed explanation of the OAuth 2.0 flow, visit RFC 6749 Specification. Regarding a step by step solution, you ought to see some tutorials such as this article explaining how to create a Spring REST API using OAuth 2.0. This article goes through code as well as creating Postman requests. With regards to mocking/tests, I've previously created a test suite for the OAuth 2.0 using TestNG and Mockito.
The more you develop and research, the more you shall find ways of improving or rather change the way you design your code. That said if you really want to abide by the OAuth 2.0 flow, you should properly understand the flow (which can be relatively vague at times) in the RFC 6749 link.
Here is the Google API clinet library sample. Try this if it helps
public class ServletSample extends AbstractAuthorizationCodeServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException {
// do stuff
}
#Override
protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException {
GenericUrl url = new GenericUrl(req.getRequestURL().toString());
url.setRawPath("/oauth2callback");
return url.build();
}
#Override
protected AuthorizationCodeFlow initializeFlow() throws IOException {
return new AuthorizationCodeFlow.Builder(BearerToken.authorizationHeaderAccessMethod(),
new NetHttpTransport(),
new JacksonFactory(),
new GenericUrl("https://server.example.com/token"),
new BasicAuthentication("s6BhdRkqt3", "7Fjfp0ZBr1KtDRbnfVdmIw"),
"s6BhdRkqt3",
"https://server.example.com/authorize").setCredentialDataStore(
StoredCredential.getDefaultDataStore(
new FileDataStoreFactory(new File("datastoredir"))))
.build();
}
#Override
protected String getUserId(HttpServletRequest req) throws ServletException, IOException {
// return user ID
}
}
public class ServletCallbackSample extends AbstractAuthorizationCodeCallbackServlet {
#Override
protected void onSuccess(HttpServletRequest req, HttpServletResponse resp, Credential credential)
throws ServletException, IOException {
resp.sendRedirect("/");
}
#Override
protected void onError(
HttpServletRequest req, HttpServletResponse resp, AuthorizationCodeResponseUrl errorResponse)
throws ServletException, IOException {
// handle error
}
#Override
protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException {
GenericUrl url = new GenericUrl(req.getRequestURL().toString());
url.setRawPath("/oauth2callback");
return url.build();
}
#Override
protected AuthorizationCodeFlow initializeFlow() throws IOException {
return new AuthorizationCodeFlow.Builder(BearerToken.authorizationHeaderAccessMethod(),
new NetHttpTransport(),
new JacksonFactory(),
new GenericUrl("https://server.example.com/token"),
new BasicAuthentication("s6BhdRkqt3", "7Fjfp0ZBr1KtDRbnfVdmIw"),
"s6BhdRkqt3",
"https://server.example.com/authorize").setCredentialDataStore(
StoredCredential.getDefaultDataStore(
new FileDataStoreFactory(new File("datastoredir"))))
.build();
}
#Override
protected String getUserId(HttpServletRequest req) throws ServletException, IOException {
// return user ID
}
}
https://github.com/spring-projects/spring-security-oauth/tree/master/samples/oauth2 contains sample code for performing oauth2 using Spring Security.

How to create multiple asynchronous java filters?

I'm trying to create a Java application with multiple asynchronous filters, but cannot seem to get them to work well together. I think the main issue is in the run() method I don't know what to do to pass along the request to the next filter in the chain. I've tried chain.doFilter(request, response), but that doesn't seem to work, and there are dispatch() and complete() APIs available on the AsyncContext, but those seem to close out the entire AsyncContext. It seems like there must be another way to get this to work. Below is a snippet of the filter I'm using - the second filter looks almost identical.
Note: I'm adding headers to try and figure out what is getting called.
#Override
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
final AsyncContext asyncContext = request.startAsync();
final HttpServletResponse res = (HttpServletResponse) response;
asyncContext.addListener(new AsyncListener() {
#Override
public void onComplete(AsyncEvent event) throws IOException {
res.addHeader("S-AST2", "onComplete");
}
#Override
public void onTimeout(AsyncEvent event) throws IOException {
res.addHeader("S-AST3", "onTimeout");
}
#Override
public void onError(AsyncEvent event) throws IOException {
res.addHeader("S-AST4", "onError");
}
#Override
public void onStartAsync(AsyncEvent event) throws IOException {
res.addHeader("S-AST0", "onStartAsync");
}
});
asyncContext.start(new Runnable() {
#Override
public void run() {
res.addHeader("S-AST1", "before");
// This doesn't seem to work...
asyncContext.dispatch();
// ... or this ...
asyncContext.complete();
// ... or this ...
chain.doFilter(request, response);
}
});
}
Thanks for any insight!
There are two parts to this answer.
1) The chain.doFilter(request, response); is still required.
2) The reason this was not working is that in each filter and in the servlet I was calling request.startAsync(), which started a new async process, rather than using an existing one. So if the filter started an async process, and the servlet also started one, it would overwrite/ignore the one started in the filter. To solve this you must check to see if an async process is already started, by calling request.isAsyncStarted(), and if it is, rather than starting a new async context, you should get the existing one with request.getAsyncContext(). Below is a helper class I created to do this for each servlet and filter, so that I can just call AsyncHelper.getAsyncContext(request, response) and it will either retrieve the existing AsyncContext, or create a new one.
public class AsyncHelper {
public static AsyncContext getAsyncContext(ServletRequest request, ServletResponse response) {
AsyncContext asyncContext = null;
if (request.isAsyncStarted()) {
asyncContext = request.getAsyncContext();
}
else {
asyncContext = request.startAsync(request, response);
asyncContext.setTimeout(2000);
}
return asyncContext;
}
}
I had the need to decorate the response, and I did not know whether the underlying servlet was doing async or not, or if it already had completed. On Jetty 9.1.x I solved it by expecting IllegalStateException
The following example illustrates how to wrap the response (Using the custom BufferingHttpServletResponseWrapper that buffers all that is written to the response) to intercept input so that it can be decorated.
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
final HttpServletRequest httpServletRequest = (HttpServletRequest) request;
final HttpServletResponse httpServletResponse = (HttpServletResponse) response;
// Buffer the output to a string in order to calculate its signature and add the signature to a header before it's sent to the client
final BufferingHttpServletResponseWrapper responseWrapper = new BufferingHttpServletResponseWrapper(httpServletResponse);
chain.doFilter(httpServletRequest, responseWrapper);
// This is the only way I can see that will safely let us know if we should treat this as an active async request or not.
try {
httpServletRequest.getAsyncContext().addListener(new AsyncListener() {
#Override
public void onComplete(AsyncEvent event) throws IOException {
LOG.debug("onComplete {}", event);
decorateResponse(responseWrapper);
}
#Override
public void onTimeout(AsyncEvent event) throws IOException {
LOG.debug("onTimeout {}", event);
}
#Override
public void onError(AsyncEvent event) throws IOException {
LOG.debug("onError {}", event);
}
#Override
public void onStartAsync(AsyncEvent event) throws IOException {
LOG.debug("onStartAsync {}", event);
event.getAsyncContext().addListener(this);
}
}
, httpServletRequest, responseWrapper);
LOG.debug("After chain.doFilter, async was started");
} catch (IllegalStateException e) {
LOG.debug("Async not active it appears... {}", e.getMessage());
decorateResponse(responseWrapper);
}
}

Avoiding the endless loop in JSP servlet mapping

I've got this issue, recently I read about the REST arquitecture and it makes a perfect sense, so I'd like to achieve a RESTful web application.
Now, I'm following the Front Controller pattern that means that all of the URL mappings go to the controller.java servlet, I map the by specific URLs, not by using the /* wildcard,
the controller implements the four HTTP methods POST,GET,PUT,DELETE, each method calls the controllers service method and there I determine based on the HttpServletRequest and pathInfo the action to execute.
Controller.java
#Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
IAction action;
View view;
try {
action = ActionFactory.produceAction(req);
view = action.execute(req, resp);
switch (view.getDispatchMethod()) {
case REDIRECT:
resp.sendRedirect(resp.encodeURL(view.getResource()));
break;
case FORWARD:
req.getRequestDispatcher(view.getResource()).forward(req, resp);
break;
case INCLUDE:
req.getRequestDispatcher(view.getResource()).include(req,resp);
break;
default:
}
} catch (ActionFailedException uae) {
req.setAttribute("ActionName", "Action");
req.setAttribute("FailCause", uae.getMessage());
req.getRequestDispatcher(VIEW_FAIL.getResource()).forward(req, resp);
}
}
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
this.service(req, resp);
}
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.service(req, resp);
}
#Override
protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.service(req, resp);
}
#Override
protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.service(req, resp);
}
I've run into a particular issue when loading a specific order by the URI /orders/*, it is mapped to the controller servlet, the the action is executed and I load the appropriate order the action returns a View.java class
//ommited accessors and mutators for brevety.
public class View {
public enum DispatchMethod {
INCLUDE, FORWARD, REDIRECT
}
private DispatchMethod dispatchMethod;
private String resource;
public View(DispatchMethod dispatchMethod, String resource) {
this.dispatchMethod = dispatchMethod;
this.resource = resource;
}
}
Then the request is dispatched according to the getDispatchMethod() of the returned view.
Now, here is where the loop gets triggered, I use the following URL, myapp/orders/78965 /orders/* gets mapped to controller.java the appropriate action is executed and the correct order is found by the pathInfo() the returned view is new View(View.DispatchMethod.FORWARD,"order_details.jsp") the problem is that with the three available dispatch methods REDIRECT,FORWARD and INCLUDE a request is re-triggered on the URL and so on and on and on I never reach the order_details.jsp that renders the data.
So, how would you avoid the looping, as I'd like to preserve the URI displaying the order number I use the forward method, also, I'd like to do it using servlets, I've heard of the UrlRewriteFilter maybe in the future, but right now, how would it be done using "Plain Vanilla" since I'm using the Front Controller pattern, will it be necessary to add an additional servlet in the /orders/ URI ?
Any help or insights is truly appreciated.
EDIT 1:
Pasted the source code of the controller, a very basic one, I have my suspicions that the way the service method calls all of the overriden do[Method] of the servlet is triggering the loop and that it may be solved by splittig them.
Implementing a RESTful HTTP interface in Java is a lot easier using a JAX-RS implementation like RESTEasy or Jersey.
Using a Front Controller to dispatch requests to the right resource is a good approach, it's exactly the approach taken by these JAX-RS frameworks. I fear you may be re-inventing the wheel here by writing a bespoke URL parsing and dispatching mechanism when this can be taken off-the-shelf.
JAX-RS is a lightweight way to expose resources. By using a couple of simple annotations you can expose a REST interface without any plumbing required. For example:
public class Order {
#GET
#Path("/orders/{orderId}")
#Produces("text/html")
public void getOrder(#Context HttpServletResponse response,
#Context HttpServletRequest request,
#PathParam("orderId") String orderId) throws ServletException, IOException {
// ... create view and add to request here
request.getRequestDispatcher("orders.jsp").forward(request, response);
}
}
You can see how simple it is to attach this class to a URL path (using the #Path annotation), and how easily you can parse values from the URL using #PathParam. Since you get all the plumbing/dispatching/parsing off-the-shelf, you can concentrate on the bits of your app that are specific to your domain (such as what an order contains).

Is it possible to write a servlet filter to take inspect HTTP response codes? [duplicate]

This question already has answers here:
How can I get the HTTP status code out of a ServletResponse in a ServletFilter?
(7 answers)
Closed 7 years ago.
Is it possible to write a servlet filter to take inspect HTTP response codes?
I want to write a filter that will non-destructively inspect outgoing HTTP response codes. But, there does not seem to be a getResponseCode() like method on the Response object.
It is also not clear to me how unhandled exceptions from the servlet are supposed to be dealt with. I really don't want this filter to actually set anything. Passive is good.
Ideas?
(My other approach involves writing a custom Tomcat valve, but that is not so portable.)
you can wrap your outgoing response using HttpServletResponseWrapper:
class GetStatusWrapper extends HttpServletResponseWrapper {
private int status;
GetStatusWrapper(HttpServletResponse response) {
super(response);
}
#Override
public void setStatus(int sc) {
super.setStatus(sc);
status = sc;
}
public int getStatus() {
return status;
}
}
then in your filter:
public class GetStatusResponseFilter implements Filter {
#Override
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain filterChain)
throws IOException, ServletException {
GetStatusWrapper wrapper;
wrapper = new GetStatusWrapper((HttpServletResponse) response);
filterChain.doFilter(request, wrapper);
System.out.println("status = " + wrapper.getStatus());
}
#Override
public void init(FilterConfig arg0) throws ServletException {
}
#Override
public void destroy() {
}
}
Would you consider writing a proxy wrapper around the original response class? This way you can handle events / method calls on the object.

Categories

Resources