Websocket + Vraptor

Olá pessoal, bom dia!

Gostaria de saber se já implementaram algo com websockets + vraptor.

A minha necessidade é fazer um server websocket, que quando um objeto é inserido/alterado/removido na base de dados via hibernate, quero que o server emita uma mensagem broadcast e tal, notificando os usuários.

Alguém já implementou algo assim?
Pode me dar uma ajuda?

Já vi como implementar no Tomcat 7, mas ele usa uma Servet, e pelo que andei lendo aqui no Guj, terei problemas porque o VRaptor usa um Filter.

Forte abraço, valeu!

Pois eh… uma tentativa que talvez funcione é pegar o filtro do VRaptor:

e trocar o implements Filter por extends HttpServlet…

o que vai dar pau é a falta do FilterChain… mas tente usar sem por enquanto e ver no que rola.

Daí eu te ajudo a resolver os problemas que aparecerem =)

Certo Lucas, eu vi as dicas que você deu num outro tópico sobre isso
E fiz dessa maneira. Eu não conheço muito sobre servlets

@WebServlet
public class VRaptorServlet extends HttpServlet{
	private static final long serialVersionUID = 1L;
	
	private ContainerProvider provider;
	private ServletContext servletContext;

	private StaticContentHandler staticHandler;

	private static final Logger logger = LoggerFactory.getLogger(VRaptor.class);

	public void destroy() {
		provider.stop();
		provider = null;
		servletContext = null;
	}

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse res)
			throws ServletException, IOException {

		if (!(req instanceof HttpServletRequest) || !(res instanceof HttpServletResponse)) {
			throw new ServletException(
					"VRaptor must be run inside a Servlet environment. Portlets and others aren't supported.");
		}

		final HttpServletRequest baseRequest = (HttpServletRequest) req;
		final HttpServletResponse baseResponse = (HttpServletResponse) res;

		if (staticHandler.requestingStaticFile(baseRequest)) {
			staticHandler.deferProcessingToContainer(null, baseRequest, baseResponse);
		} else {
			logger.debug("VRaptor received a new request");
			logger.trace("Request: {}", req);

			VRaptorRequest mutableRequest = new VRaptorRequest(baseRequest);
			VRaptorResponse mutableResponse = new VRaptorResponse(baseResponse);

			final RequestInfo request = new RequestInfo(servletContext, null, mutableRequest, mutableResponse);
			provider.provideForRequest(request, new Execution<Object>() {
				public Object insideRequest(Container container) {
					container.instanceFor(EncodingHandler.class).setEncoding(baseRequest, baseResponse);
					container.instanceFor(RequestExecution.class).execute();
					return null;
				}
			});
			logger.debug("VRaptor ended the request");
		}
		
		super.service(req, res);
	}
	
	@Override
	public void init(ServletConfig cfg) throws ServletException {
		servletContext = cfg.getServletContext();
		BasicConfiguration config = new BasicConfiguration(servletContext);
		init(config.getProvider());
		logger.info("VRaptor 3.4.1-SNAPSHOT successfuly initialized");
	}

	void init(ContainerProvider provider) {
		this.provider = provider;
		this.provider.start(servletContext);
		this.staticHandler = provider.getContainer().instanceFor(StaticContentHandler.class);
	}

}

Eu só não consegui compreender ainda, como essa servlet passaria a requisição via ws pra a classe servidor de websocket.
Pois esse seria o papel dela, correto? ou estou enganado?

Outra dúvida, no método service, preciso chamar super.service(req, res) no final?

não era só fazer algo como request.getAsyncContext() no controller que vc quiser brincar de fazer WebSocket?

Não sei cara rs sério, não manjo nada de servlet.

Como seria o cenário?
Eu teria um controller que seria meu server websocket e essa servlet faria o mesmo papel do filtro do vraptor.
Ou essa servlet adaptada já seria o meu server?

To com muita vontade de implementar isso e contribuir com o projeto vraptor, mas não sei muito como seria.
Não sei muito bem como prosseguir.
Se puder me passar algo ou me ajudar, seria bom.

o servlet vai funcionar como se fosse o filter do vraptor e o controller vai ser o servidor do web socket.

Nunca usei isso na prática, então não sei se vou conseguir te ajudar mto… mas procura sobre o request asyncContext

Saquei.

Está dando esse erro quando tento acessar a raiz da aplicação

SEVERE: Servlet.service() for servlet VRaptorServlet threw exception
java.lang.NoSuchMethodError: javax.servlet.http.HttpServletRequest.startAsync(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;)Ljavax/servlet/AsyncContext;
	at br.com.nextrans.myone.servlet.VRaptorServlet.service(VRaptorServlet.java:81)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:291)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:602)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
	at java.lang.Thread.run(Thread.java:722)

Essa é a implementação do método service

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse res)
			throws ServletException, IOException {

		if (!(req instanceof HttpServletRequest) || !(res instanceof HttpServletResponse)) {
			throw new ServletException(
					"VRaptor must be run inside a Servlet environment. Portlets and others aren't supported.");
		}

		final HttpServletRequest baseRequest = (HttpServletRequest) req;
		final HttpServletResponse baseResponse = (HttpServletResponse) res;

		if (!staticHandler.requestingStaticFile(baseRequest)) {
			logger.debug("VRaptor received a new request");
			logger.trace("Request: {}", req);

			
			VRaptorRequest mutableRequest = new VRaptorRequest(baseRequest);
			VRaptorResponse mutableResponse = new VRaptorResponse(baseResponse);

			final RequestInfo request = new RequestInfo(servletContext, null, mutableRequest, mutableResponse);
			provider.provideForRequest(request, new Execution<Object>() {
				public Object insideRequest(Container container) {
					container.instanceFor(EncodingHandler.class).setEncoding(baseRequest, baseResponse);
					container.instanceFor(RequestExecution.class).execute();
					return null;
				}
			});
			AsyncContext aCtx = req.startAsync(req, res); // não sei onde chamar esse método
			logger.debug("VRaptor ended the request");
		}
		
	}

Alguma ideia?

vc deve estar ou deployando num servidor que não é servlet 3.0 ou vc tá com a api do servlet 2.5 no classpath.

É isso mesmo Lucas. Viajei, tava deployando o projeto no tomcat 6
Só não estou conseguindo subir o tomcat 7 no eclipse.
Fica dando essa mensagem: “[…] bootstrap.jar which is referenced by the classpath, does not exist.” Sendo que o arquivo existe.
Já tentei reinstalar o server no eclipse, mexer no User Entries, e nada.

Já teve esse problema?

vc tá usando o adapter do tomcat 7? tipo na hora de criar o servidor vc selecionou a versão 7?

Sim, isso mesmo.
new Server -> Selecionei a versão, diretório de instalação, etc.

Lucas, consegui instalar o server corretamente.

Agora quando tento acessar um controller pela url, não é mostrado nada na tela.

Meu método service está da mesma forma:

@Override
	protected void service(HttpServletRequest req, HttpServletResponse res)
			throws ServletException, IOException {

		if (!(req instanceof HttpServletRequest) || !(res instanceof HttpServletResponse)) {
			throw new ServletException(
					"VRaptor must be run inside a Servlet environment. Portlets and others aren't supported.");
		}

		final HttpServletRequest baseRequest = (HttpServletRequest) req;
		final HttpServletResponse baseResponse = (HttpServletResponse) res;

		if (!staticHandler.requestingStaticFile(baseRequest)) {
			logger.debug("VRaptor received a new request");
			logger.trace("Request: {}", req);

			
			VRaptorRequest mutableRequest = new VRaptorRequest(baseRequest);
			VRaptorResponse mutableResponse = new VRaptorResponse(baseResponse);

			final RequestInfo request = new RequestInfo(servletContext, null, mutableRequest, mutableResponse);
			provider.provideForRequest(request, new Execution<Object>() {
				public Object insideRequest(Container container) {
					container.instanceFor(EncodingHandler.class).setEncoding(baseRequest, baseResponse);
					container.instanceFor(RequestExecution.class).execute();
					return null;
				}
			});
			AsyncContext aCtx = req.startAsync(req, res); // não sei o que fazer com isso
			logger.debug("VRaptor ended the request");
		}
		
	}

Criei esse repositório https://github.com/bglbruno/vraptor-websocket

o startAsync vc faz só no controller, e só qdo vc quiser que a requisição seja web-socket.

Vc chegou a ligar o log de debug? está logando alguma coisa durante a request?