Subject no longer authenticated in session after logging in with Shiro - java

I am using Guice + Jersey + Shiro to login via a REST API and then use the same HTTP session under which I logged in to and have my permissions work for that resource.
Below is my code.
Firstly, my servlet configuration:-
public class ServletConfiguration extends GuiceServletContextListener
{
private ServletContext mServletContext;
#Override
public void contextInitialized(ServletContextEvent inEvent)
{
mServletContext = inEvent.getServletContext();
super.contextInitialized(inEvent);
}
#Override
protected Injector getInjector()
{
mServletContext.addListener(new au.com.tt.agora.configuration.CbiCleanupHttpSessionListener());
return Guice.createInjector(new JerseyServletModule() {
#Override
protected void configureServlets()
{
install(new TTShiroWebModule(mServletContext));
install(new ShiroAopModule());
filter("/*").through(GuiceShiroFilter.class);
bind(ShiroLoginResource.class);
bind(ShiroResource.class);
filter("/*").through(GuiceContainer.class);
}
});
}
}
Now, this is my test realm:-
package au.com.tt.agora.configuration.shiro;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
public class TestRealm extends AuthorizingRealm
{
#Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken inToken) throws AuthenticationException
{
UsernamePasswordToken upToken = (UsernamePasswordToken) inToken;
if (upToken.getUsername().equals("Kamal") || upToken.getUsername().equals("NotKamal"))
return new SimpleAuthenticationInfo(upToken.getUsername(), upToken.getPassword(), getName());
return null;
}
#Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection inPrincipals)
{
String username = (String) inPrincipals.fromRealm(getName()).iterator().next();
SimpleAuthorizationInfo authzInfo = new SimpleAuthorizationInfo();
if (username.equals("Kamal"))
{
authzInfo.addStringPermission("PRODMA:READ:AU");
authzInfo.addStringPermission("PRODMA:WRITE:KB");
authzInfo.addStringPermission("SUPPMA:READ:KB");
}
else
{
authzInfo.addStringPermission("PRODMA:READ:AU");
authzInfo.addStringPermission("PRODMA:WRITE:KB");
}
return authzInfo;
}
}
This is the web module
package au.com.tt.agora.configuration.shiro;
import javax.servlet.ServletContext;
import org.apache.shiro.guice.web.ShiroWebModule;
public class TTShiroWebModule extends ShiroWebModule
{
public TTShiroWebModule(ServletContext inServletContext)
{
super(inServletContext);
}
#SuppressWarnings("unchecked")
#Override
protected void configureShiroWeb()
{
bindRealm().to(TestRealm.class);
addFilterChain("**/shiroResource/*", ANON);
}
}
Here is the resource I use to login:-
package au.com.tt.agora.configuration.jaxrs.resources;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import com.google.inject.Inject;
import au.com.tt.agora.configuration.option.ClientProvider;
import au.com.tt.agora.configuration.option.ConfigurationProvider;
import au.com.tt.agora.login.web.request.LoginRequest;
import au.com.tt.agora.login.web.request.LoginResponse;
import au.com.tt.agora.login.web.service.LoginHandler;
import au.com.tt.calypso.cbi.CalypsoException;
#Path("/{client}/shiroLogin")
public class ShiroLoginResource
{
private static final String ROUTING_TOKEN_HEADER = "proxy-jroute";
#POST
#Path("/standard")
#Produces(MediaType.TEXT_PLAIN)
#Consumes(MediaType.APPLICATION_JSON)
public String login(#Context HttpServletRequest inServletRequest) throws CalypsoException
{
Subject subject = SecurityUtils.getSubject();
subject.login(new UsernamePasswordToken("Kamal", "Password", false));
return getSessionIdWithRouting(inServletRequest);
}
private String getSessionIdWithRouting(HttpServletRequest inRequest)
{
String sessionId = inRequest.getSession().getId();
return(sessionId);
}
}
And here is the resource I am calling:-
package au.com.tt.agora.configuration.jaxrs.resources;
import javax.servlet.http.HttpSession;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.inject.Inject;
#Path("/{client}/shiroResource")
public class ShiroResource
{
private static final Logger LOG = LoggerFactory.getLogger(ShiroResource.class);
#Inject
public ShiroResource()
{
}
#POST
#Path("requiresProdma.do")
#Produces(MediaType.TEXT_PLAIN)
#RequiresPermissions({ "PRODMA:*:*" })
public String prodmaRequired()
{
return "Success";
}
#POST
#Path("requiresSuppma.do")
#Produces(MediaType.TEXT_PLAIN)
#RequiresPermissions({ "SUPPMA:*:*" })
public String suppmaRequired()
{
Subject subject = SecurityUtils.getSubject();
subject.getPrincipal();
return "Success";
}
}
If I put a breakpoint into suppmaRequired and call this resource, I can see that subject is not authenticated.
My understanding on how Shiro works is obviously faulty, but I don't know what I am not doing. Can anyone point me in the right direction?
Not sure if it makes a difference, but I am using URL rewriting to access the web session.
Basically, I am using the fetch API to test this. Here is an example:-
fetch("http://localhost/app/tt/shiroLogin/standard", {
method: "POST",
headers: {
"Content-Type" : "application/json"
} ,
body: '{"username":"myName","password":"myPassword"}'
})
.then(function(res) {
return res.text();
})
.then(function(sessionId) {
return fetch("http://localhost/app/tt/shiroResource/requiresSuppma.do;JSESSIONID=" + sessionId,
{
method: "POST"
});
})
.then(function(res) {
return res.text();
})
.then(function(res) {
console.log(res);
});
I am also deploying to glassfish.

OK, this was not a Shiro problem in the end. I was using two different sessions going from the ShiroLoginResource to ShiroResource.
I forgot that you actually needed to inject with a session level object in Guice to force Guice to create a session. Stupid me.
Once I injected a session scoped dependency into ShiroLoginResource and interacted with it, then everything just worked.
I will keep this question open because it gives some useful code snippets.

Related

How should I persist a PanacheEntity with data coming from a Websocket message?

I'm trying to persist the following entity when receiving a message from the client via Websocket:
import javax.persistence.Column;
import javax.persistence.Entity;
import io.quarkus.hibernate.orm.panache.PanacheEntity;
#Entity
public class Penguin extends PanacheEntity{
#Column(name="penguin_name")
public String name;
}
The following persist works, when receiving a POST request:
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.transaction.Transactional;
import com.penguins.demo.pojos.Penguin;
#Path("/api")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public class PenguinResource {
#GET
public List<Penguin> getPenguins(){
return Penguin.listAll();
}
#POST
#Transactional
public Response addPenguin(Penguin penguin){
penguin.persist();
return Response.ok(penguin).status(201).build();
}
}
However, the following code freezes when it reaches the persist line. The message.getPenguin() method is returning an actual Penguin reference (the MessageDecoder.class is doing it's part):
import javax.websocket.OnMessage;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import com.penguins.demo.pojos.Message;
import com.penguins.demo.pojos.Penguin;
#ServerEndpoint(value = "/waddle/{user}", decoders = MessageDecoder.class, encoders = MessageEncoder.class)
public class PenguinHub {
#OnMessage
#Transactional
public void onMessage(Session session, Message message) throws IOException {
// Handle new messages
message.setFrom(users.get(session.getId()));
// it freezes on persist :(
message.getPenguin().persist();
broadcast(message);
}
}
I'm new to Panache/Hibernate, any help would be apreciated, thank you.
It worked like this:
#Inject
ManagedExecutor managedExecutor;
#Inject
TransactionManager transactionManager;
#OnMessage
public void onMessage(Session session, Message message) throws IOException {
message.setFrom(users.get(session.getId()));
managedExecutor.submit(() -> {
try{
transactionManager.begin();
parseMessage(message); // persist the entity here
transactionManager.commit();
}catch(Exception e){
e.printStackTrace();
}
});
}

Problem with cutomizing ErrorAttributeOptions in Spring Reactive

In my handler function I have this method
public Mono<ServerResponse> itemsEx(ServerRequest serverRequest) {
throw new RuntimeException("RuntimeException Occured");
}
Now, I want to handle this exception, so I override AbstractErrorWebExceptionHandler and create this class.
package com.learnreactivespring.learnreactivespring.exception;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.reactive.error.AbstractErrorWebExceptionHandler;
import org.springframework.boot.web.error.ErrorAttributeOptions;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.*;
import reactor.core.publisher.Mono;
import java.util.Map;
#Component
#Slf4j
public class FunctionalErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler {
public FunctionalErrorWebExceptionHandler(ErrorAttributes errorAttributes,
ApplicationContext applicationContext,
ServerCodecConfigurer serverCodecConfigurer) {
super(errorAttributes, new ResourceProperties(), applicationContext);
super.setMessageWriters(serverCodecConfigurer.getWriters());
super.setMessageReaders(serverCodecConfigurer.getReaders());
}
#Override
protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
}
private Mono<ServerResponse> renderErrorResponse(ServerRequest serverRequest) {
ErrorAttributeOptions errorAttributes = ErrorAttributeOptions.of(ErrorAttributeOptions.Include.MESSAGE);
Map<String, Object> errorAttributesMap = getErrorAttributes(serverRequest, errorAttributes);
log.info("errorAttributesMap : " + errorAttributesMap);
return ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(errorAttributesMap.get("message")));
}
The problem is, that I have still a Stacktrace in my terminal... but I explicitly defined ErrorAttributeOptions only with message.
My current version of Spring Boot is 2.3.1.RELEASE. In previous version (2.1.1) I didn't have this problem because I used to this
package com.learnreactivespring.exception;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.template.TemplateAvailabilityProviders;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.reactive.error.AbstractErrorWebExceptionHandler;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.*;
import reactor.core.publisher.Mono;
import java.util.Map;
#Component
#Slf4j
public class FunctionalErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler {
public FunctionalErrorWebExceptionHandler(ErrorAttributes errorAttributes,
ApplicationContext applicationContext,
ServerCodecConfigurer serverCodecConfigurer) {
super(errorAttributes, new ResourceProperties(), applicationContext);
super.setMessageWriters(serverCodecConfigurer.getWriters());
super.setMessageReaders(serverCodecConfigurer.getReaders());
}
#Override
protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
}
private Mono<ServerResponse> renderErrorResponse(ServerRequest serverRequest) {
Map<String, Object> errorAttributesMap = getErrorAttributes(serverRequest, false);
log.info("errorAttributesMap : " + errorAttributesMap);
return ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromObject(errorAttributesMap.get("message")));
}
}
Now, after bumped version of Spring Boot this issue occured.
You should use ErrorAttributeOptions.defaults(). But note that by default message is always empty (and stacktrace is not present).
So you probably want to use something like this:
ErrorAttributeOptions options = ErrorAttributeOptions
.defaults()
.including(ErrorAttributeOptions.Include.MESSAGE)
;
And use .excluding(.) if you want to exclude something.

How to parse REST API STREAM

I am sending a get request to the server and server returns the following two responses. These responses are received as the event occurs on servers in streams (like id1,id2,id3,id4.....and so on) not in one shot.
Now, I need to take these response one by one and parse it and then save it the objects for further use.
How do i achieve this java 8 and spring MVC?
id: 1
data: {"event_type":"ABC","business_call_type":"XYZ","agent_number":"nnn","call_recording":null,"number":"0000","uuid":"a","call_direction":"Outbound","caller":"+100000000000","customer_number":"+100000000000","version":"1.0","k_number":"+917303454203","type":"AGENT_CALL","unique_id":"0","call_solution":"xx","FreeSWITCH_IPv4":"11111","Event_Date_Local":"2020-03-28 11:46:47"}
id: 2
data: {"event_type":"AGENT_ANSWER","business_call_type":"Outbound","agent_number":"+1111111111","call_recording":null,"number":"+22222222","uuid":"bbbbbbbbbbbbbb","call_direction":"Outbound","caller":"+100000000000","customer_number":"+100000000000","version":"1.0","k_number":"+1111111111","type":"AGENT_ANSWER","unique_id":"bbbbbbbbbb","call_solution":"xx","FreeSWITCH_IPv4":"0.0.0.0","Event_Date_Local":"2020-03-28 11:47:00"}
below is the code used foe above json parsing.
import java.util.HashMap;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureCallback;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.client.AsyncRestTemplate;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.context.request.async.DeferredResult;
import com.psg.async_tasks.controller;
import com.psg.dao.CtiIntegrationdao;
// #Controller
#Service
public class ListningService {
private static final Logger logger = Logger.getLogger(ListningService.class.getName());
#Autowired
CtiIntegrationdao daoCtiInt;
//#RequestMapping({"list"})
#PostConstruct
public void ListningReponse() {
HashMap<String,String> results=daoCtiInt.getKnolarity_Config();
String endpoint;
endpoint=results.get("30");
endpoint=endpoint.replace("<<AUTH>>",results.get("26"));
logger.info(endpoint);
logger.info("============================================================================================#postconstruct=========");
AsyncRestTemplate asyncrestTemplate = new AsyncRestTemplate();
try {
final DeferredResult<String> result = new DeferredResult<>();
ListenableFuture<ResponseEntity<String>> futureEntity = asyncrestTemplate.getForEntity(endpoint, String.class);
logger.info("IN TRY");
logger.info(futureEntity.toString());
futureEntity.addCallback(new ListenableFutureCallback<ResponseEntity<String>>() {
#Override
public void onSuccess(ResponseEntity<String> result) {
String[] idno = result.getBody().split("\\R", 3);
System.out.println("==================="+idno[0]);
String responseBody =result.getBody().replaceAll("id: (\\d+)","").replace("data: ","");;
logger.info("-----responsebody-----"+responseBody);
logger.info("-----responsebody-----"+result.getBody());
// logger.info("-----responsebody-----"+result.getBody().getAgent_number());
// logger.info("-----responsebody-----"+result.getBody().getBusiness_call_type());
// logger.info("-----responsebody-----"+result.getBody().getCall_duration());
// logger.info("-----responsebody-----"+result.getBody().getCall_recording());
// logger.info("-----responsebody-----"+result.getBody().getCall_solution());
// logger.info("-----responsebody-----"+result.getBody().getCall_Type());
// logger.info("-----responsebody-----"+result.getBody().getDestination());
}
#Override
public void onFailure(Throwable ex) {
result.setErrorResult(ex.getMessage());
logger.info("------------Failure Block"+result.toString());
}
});
}catch(HttpClientErrorException ex) {
logger.info(ex.getMessage());
}catch(Exception ex) {
ex.printStackTrace();
}
}
}

Can't Access Atmosphere MetaBroadcaster in Spring Boot Controller

I have a simple chat application set up using Spring Boot (1.3.2) and Atmosphere (2.4.2).
Here is my WebSocketConfigurer:
package com.chat.shared.websocket;
import java.util.Collections;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.apache.catalina.Context;
import org.apache.tomcat.websocket.server.WsSci;
import org.atmosphere.cpr.AtmosphereFramework;
import org.atmosphere.cpr.AtmosphereServlet;
import org.atmosphere.cpr.MetaBroadcaster;
import org.springframework.boot.context.embedded.ServletContextInitializer;
import org.springframework.boot.context.embedded.tomcat.TomcatContextCustomizer;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.chat.privatechat.ChatChannel;
#Configuration
public class WebSocketConfigurer implements ServletContextInitializer {
#Bean
public TomcatEmbeddedServletContainerFactory tomcatContainerFactory() {
TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
factory.setTomcatContextCustomizers(Collections.singletonList(tomcatContextCustomizer()));
return factory;
}
#Bean
public TomcatContextCustomizer tomcatContextCustomizer() {
return new TomcatContextCustomizer() {
#Override
public void customize(Context context) {
context.addServletContainerInitializer(new WsSci(), null);
}
};
}
#Bean
public AtmosphereServlet atmosphereServlet() {
return new AtmosphereServlet();
}
#Bean
public AtmosphereFramework atmosphereFramework() {
return atmosphereServlet().framework();
}
#Bean
public MetaBroadcaster metaBroadcaster() {
AtmosphereFramework framework = atmosphereFramework();
return framework.metaBroadcaster();
}
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
configureAtmosphere(atmosphereServlet(), servletContext);
}
private void configureAtmosphere(AtmosphereServlet servlet, ServletContext servletContext) {
ServletRegistration.Dynamic reg = servletContext.addServlet("atmosphereServlet", servlet);
reg.setInitParameter("org.atmosphere.cpr.packages", ChatChannel.class.getPackage().getName());
reg.setInitParameter("org.atmosphere.cpr.broadcasterClass", "org.atmosphere.plugin.hazelcast.HazelcastBroadcaster");
reg.setInitParameter("org.atmosphere.cpr.broadcaster.maxProcessingThreads", "10");
reg.setInitParameter("org.atmosphere.cpr.broadcaster.maxAsyncWriteThreads", "10");
reg.setInitParameter("org.atmosphere.interceptor.HeartbeatInterceptor.clientHeartbeatFrequencyInSeconds", "10");
servletContext.addListener(new org.atmosphere.cpr.SessionSupport());
reg.addMapping("/chat/*");
reg.setLoadOnStartup(0);
reg.setAsyncSupported(true);
}
}
And here is how I'm currently leveraging it in the ChatChannel:
package com.chat.privatechat;
import com.chat.privatechat.DTOs.ChatMessageDTO;
import com.chat.shared.localmessagebus.LocalMessage;
import com.chat.shared.localmessagebus.LocalMessageBus;
import org.atmosphere.config.service.Disconnect;
import org.atmosphere.config.service.Get;
import org.atmosphere.config.service.ManagedService;
import org.atmosphere.config.service.PathParam;
import org.atmosphere.config.service.Ready;
import org.atmosphere.cpr.AtmosphereResource;
import org.atmosphere.cpr.AtmosphereResourceEvent;
import org.atmosphere.cpr.AtmosphereResourceFactory;
import org.atmosphere.cpr.BroadcasterFactory;
import org.atmosphere.cpr.MetaBroadcaster;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import javax.inject.Inject;
#ManagedService(path = "/chat/{channel: [a-zA-Z][a-zA-Z_0-9]*}")
public class ChatChannel {
#PathParam("channel")
private String channelUuid;
#Inject
private BroadcasterFactory factory;
#Inject
private AtmosphereResourceFactory resourceFactory;
#Inject
private MetaBroadcaster metaBroadcaster;
#Get
public void init(AtmosphereResource resource) {
resource.getResponse().setCharacterEncoding(StandardCharsets.UTF_8.name());
}
#Ready
public void onReady(final AtmosphereResource resource) {
String userId = resource.getRequest().getHeader("userId");
System.out.println("User " + userId + " has connected.");
}
#Disconnect
public void onDisconnect(AtmosphereResourceEvent event) {
String userId = event.getResource().getRequest().getHeader("userId");
System.out.println("User " + userId + " has disconnected");
}
#org.atmosphere.config.service.Message(encoders = MessageEncoderDecoder.class, decoders = MessageEncoderDecoder.class)
public ChatMessageDTO onMessage(ChatMessageDTO chatMessage) throws IOException {
LocalMessageBus.manager().send(new LocalMessage<ChatMessageDTO>(chatMessage));
return chatMessage;
}
}
This setup works great (users in a conversation are connected to a "channel" and the messages are sent/received immediately. LocalMessageBus is a simple message bus that will eventually be replaced by a proper message broker).
Although I don't have a use case for this, I went to set up a MetaBroadcaster in my ChatController to see if I could broadcast messages from there. Unfortunately, I am not able to properly inject/reference the MetaBroadcaster as it is always null. Here's the important bits of the ChatController:
package com.chat.privatechat;
import java.util.List;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import com.chat.privatechat.DTOs.ChatMessageDTO;
import com.chat.privatechat.DTOs.ChatSessionInitializationDTO;
import com.chat.privatechat.DTOs.EstablishedChatSessionDTO;
import com.chat.shared.http.JSONResponseHelper;
import com.chat.user.UserService;
import com.chat.user.exceptions.IsSameUserException;
import com.chat.user.exceptions.UserNotFoundException;
import com.chat.user.strategies.UserRetrievalByIdStrategy;
#Controller
public class ChatController {
#Autowired
private ChatService chatService;
#Autowired
private BeanFactory beanFactory;
#Autowired
private UserService userService;
#Inject
private MetaBroadcaster metaBroadcaster;
#RequestMapping(value="/api/chat/session", method=RequestMethod.PUT, produces="application/json", consumes="application/json")
public ResponseEntity<String> establishChatSession(#RequestBody ChatSessionInitializationDTO initialChatSession) throws IsSameUserException, BeansException, UserNotFoundException {
...
}
#RequestMapping(value="/api/chat/session/{channelUuid}", method=RequestMethod.GET, produces="application/json")
public ResponseEntity<String> getExistingChatSessionMessages(#PathVariable("channelUuid") String channelUuid) {
...
}
}
Injecting/Autowiring MetaBroadcaster nor bringing in metaBroadcaster bean from the BeanFactory work. I've searched and searched and searched without a good solution. It seems like the bean in not accessible in this Spring Controller context and I'm running out of ideas.
Thanks you for any input!
NOTE: These are the Atmosphere deps I have:
<dependency>
<groupId>org.atmosphere</groupId>
<artifactId>atmosphere-runtime</artifactId>
<version>2.4.2</version>
</dependency>
<dependency>
<groupId>org.atmosphere</groupId>
<artifactId>atmosphere-spring</artifactId>
<version>2.4.2</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>atmosphere-javascript</artifactId>
<version>2.2.3</version>
</dependency>
<dependency>
<groupId>org.atmosphere</groupId>
<artifactId>atmosphere-hazelcast</artifactId>
<version>2.4.2</version>
</dependency>

How to configure embedded jetty to access Jersey resources?

I'm trying to configure embedded jetty to talk to my Jersey resources but I can't figure out how to do it. I've tried a couple of different things but nothing seems to work. The jetty tutorials don't really handle how to do it with Jersey. Any code suggestions or links are greatly appreciated
EDIT:
package pojo;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.glassfish.jersey.servlet.ServletContainer;
public class Main {
public static void main(String[] args) throws Exception {
Server server = new Server(8112);
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
server.setHandler(context);
ServletHolder h = new ServletHolder(new ServletContainer());
h.setInitParameter("com.sun.jersey.config.property.resourceConfigClass", "com.sun.jersey.api.core.PackagesResourceConfig");
h.setInitParameter("com.sun.jersey.config.property.packages", "resources");
h.setInitOrder(1);
context.addServlet(h, "/*");
try
{
server.start();
server.join();
}
catch (Throwable t)
{
t.printStackTrace(System.err);
}
Trying to connect to this class:
package resources;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.UriInfo;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.Timer;
import java.util.ArrayList;
import java.util.List;
import pojo.Party;
#Path("/parties")
public class AllPartiesResource {
#Context
UriInfo url;
#Context
Request request;
String name;
public static final Timer allTime = DBConnection.registry.timer(MetricRegistry.name("Timer","all-parties"));
#GET
#Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
public List<Party> getAllParties() throws Exception
{
final Timer.Context context=allTime.time(); //start the timer
List<Party> list = new ArrayList<Party>();
DBConnection.readAllData();
list.addAll(DBConnection.getPartyCollection().values());
context.stop(); //stops timer
return list;
// ---> code for Jackson
// String string;
// DBConnection.readAllData();
// ObjectMapper jsonMapper = new ObjectMapper();
// string=jsonMapper.writeValueAsString(DBConnection.getPartyCollection());
// return string;
}
#GET
#Path("count")
#Produces(MediaType.TEXT_PLAIN)
public String getPartyCount() throws Exception
{
DBConnection.readAllData();
return String.valueOf(DBConnection.getPartyCollection().size());
}
#Path("{party}") //points to OnePartyResource.class
public OnePartyResource getParty(#PathParam("party")String party)
{
name = party;
return new OnePartyResource(url,request,party);
}
}
You're mixing 2 versions of Jersey in your code together - ServletContainer from Jersey 2.x (package org.glassfish.jersey.*) and properties from Jersey 1.x (package/prefix com.sun.jersey.*).
To deploy your app using Jersey 2.x change these two lines
h.setInitParameter("com.sun.jersey.config.property.resourceConfigClass", "com.sun.jersey.api.core.PackagesResourceConfig");
h.setInitParameter("com.sun.jersey.config.property.packages", "resources");
from your main method to
h.setInitParameter(ServerProperties.PROVIDER_PACKAGES, "resources");
and check the other ServerProperties you may find useful.

Categories

Resources