Null pointer when calling #SessionScoped from #RequestScoped - java

I have a #RequestScoped bean that calls a method from a #SessionScoped one. Inside the last one, I'm getting a NullPointerException when I try to get a java.util.logging.Logger. This doesn't happens if I call the same method from the #SessionScoped directly, not from the other bean...can somebody tell me why is this happening??
The #RequestScoped bean:
#RequestScoped
public class IndexBean {
#Inject
private Auth auth;
public void redirect() throws IOException {
auth.logout();
}
}
And the #SessionScoped one:
#SessionScoped
public class Auth implements Serializable {
public void logout() {
Logger.getLogger(Auth.class.getName()).log(Level.INFO,"Logout");
}
}
The exception arises when I call the redirect() method.

Related

How to Pass Object from ContainerRequestFilter to Resource

How can/should I pass an object from a ContainerRequestFilter to a (post-matching) resource in (JAX-RS) Resteasy version 3.0.11 that has undertow embedded and uses Guice?
The method ContainerRequestContext#setProperty stores values which are synced with the HttpServletRequest. So with plain JAX-RS you can store an attribute like this:
#Provider
public class SomeFilter implements ContainerRequestFilter {
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
requestContext.setProperty("someProperty", "someValue");
}
}
And afterwards you can obtain it in your resource class:
#GET
public Response someMethod(#Context org.jboss.resteasy.spi.HttpRequest request) {
return Response.ok(request.getAttribute("someProperty")).build();
}
With CDI you also can inject any bean in the filter and resource class:
#Provider
public class SomeFilter implements ContainerRequestFilter {
#Inject
private SomeBean someBean;
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
someBean.setFoo("bar");
}
}
In your resource class:
#Inject
private SomeBean someBean;
#GET
public Response someMethod() {
return Response.ok(someBean.getFoo()).build();
}
I'd expect the same to be working with Guice.
Update: As #bakil pointed out correctly you should use a #RequestScoped bean if the object you want to pass should only be associated with the current request.

Testing a Spring MVC Handler interceptor with a session scoped bean dependency

I have a problem I'm not able to solve. I have searched on the internet and on Stackoverflow but could not find how to solve the problem.
I want to test a Spring MVC Handler interceptor. This interceptor has a "session" scope bean as a dependency.
I tried to reduce the code as much as possible. Here is the code:
The src part :
#EnableWebMvc
#Configuration
#ComponentScan(basePackages = { "..." })
public class SpringMvcConfiguration extends WebMvcConfigurerAdapter {
#Override
public void addInterceptors(InterceptorRegistry interceptorRegistry) {
interceptorRegistry.addInterceptor(initializeUserLanguageHandler());
}
#Bean
public InitializeUserLanguageHandler initializeUserLanguageHandler() {
return new InitializeUserLanguageHandler();
}
#Bean
#Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public SessionBean sessionBean() {
return new SessionBean();
}
}
#Component
public class InitializeUserLanguageHandler extends AbstractHandlerInterceptor {
#Autowired
private SessionBean sessionBean;
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (sessionBean.getLanguage() == null) {
sessionBean.setLanguage(getUserLanguage());
}
return true;
}
}
The test part:
#WebAppConfiguration
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = SpringMvcConfiguration.class)
public class BaseSpringMvcIntegrationTest {
#Resource
protected WebApplicationContext webApplicationContext;
protected MockMvc mockMvc;
#Before
public void setUp() {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
}
public class InitializeUserLanguageHandlerTest extends BaseSpringMvcIntegrationTest {
#Autowired
private SessionBean sessionBean;
#Autowired
private MockHttpSession mockHttpSession;
#Test
public void testLanguageIsInitializedOnlyOnce() throws Exception {
MockHttpSession mocksession = new MockHttpSession();
// It is null, this is because the interceptor has not been called yet
assertEquals(null, sessionBean.getLanguage());
// This line will call the interceptor and set language to "nl"
mockMvc.perform(get("/").session(mocksession).principal(getUser("nl")));
// It is null, but I expect it to be "nl"
assertEquals(null, sessionBean.getLanguage());
// Let's try again
mockMvc.perform(get("/").session(mocksession).principal(getUser("fr")));
// It is null, but I expect it to be "nl"
assertEquals(null, sessionBean.getLanguage());
}
}
You can see in the test class "InitializeUserLanguageHandlerTest" that I have some assertions.
The first time I call:
mockMvc.perform(get("/").session(mocksession).principal(getUser()));
The code in the interceptor is executed and language is set to "nl". Therefore, in my test, I would have expected that sessionBean.getLanguage() would return me "nl", but it is not. I don't understand why.
So I'm calling the perform again, the interceptor code is executed again, and calling sessionBean.getLanguage() returns "nl".
It seems I've two SessionBean instances, one in my test and the other in the source. But when I look at the SessionBean variable in Eclipse in Debug mode, they have the same ID.
If I change the "session" scope to "application" scope, it is working properly.
Can somebody help me ?
Thank you.
Here is one way to solve the problem, not sure it is the best though.
#ContextConfiguration(classes = {SpringMvcConfiguration.class, InitializeUserLanguageHandlerTest.BeanConfig.class})
public class InitializeUserLanguageHandlerTest extends BaseSpringMvcIntegrationTest {
#Configuration
public static class BeanConfig {
#Bean(name = "sessionBean")
public SessionBean sessionBean() {
return new SessionBean();
}
}
...
}

Can't get viewScoped bean from a SessionScoped bean

i would need to get a viewScoped managed bean from a sessionScoped managed bean. I tried firstly using the #ManagedProperty annotation, but i discovered immediately the it does not work and i know why. Secondly i tried to use the following method:
Map<String, Object> viewMap = FacesContext.getCurrentInstance().getViewRoot().getViewMap();
PulsantieraBean pulsantiera = (PulsantieraBean) viewMap.get("#{pulsantiera}");
but when i access in debug to the objects, pulsantiera is null and viewMap object contains only another viewScoped managed bean.
The PulsantieraBean class is declared in the following way:
#ViewScoped
#ManagedBean(name = NomeBean.PULSANTIERA)
public class PulsantieraBean extends ControllerBaseBean implements Serializable {
whereas the class in which i do the request is declared as the following
#SessionScoped
#ManagedBean(name = NomeBean.IDF_TAB_IMPORTI)
public class IdfTabImportiBean extends ControllerBaseBean implements Serializable {
I do the request inside a method in which i am sure the viewScoped managed bean PulsantieraBean exists.
Any help would be appreciated.
Thanks,
Marco
#Named(value = "controladorMB")
#SessionScoped
public class ControladorMB implements Serializable {}
call ControladorMB from ListadoFacturasMB
#Named(value = "listadoFacturasMB")
#SessionScoped
public class ListadoFacturasMB implements Serializable {
public void example() {
try {
FacesContext ctx = FacesContext.getCurrentInstance();
ValueExpression vex =ctx.getApplication().getExpressionFactory().createValueExpression(ctx.getELContext(), "#{controladorMB}", ControladorMB.class);
ControladorMB gMB = (ControladorMB) vex.getValue(ctx.getELContext());
} catch (Exception e) {
JsfUtil.addErrorMessage(e, "Error: buscarPersonalizado() " + e.getMessage());
}
}
}

Access sessionscoped managedbean values in requestscoped/viewscoped managedbean

I'm trying to access an object in my sessioncontroller (sessionscoped bean) from a managedbean. The sessionobject gets created when you log in. Then when I try to persist from the requestscoped bean and I need the login-object from the sessioncontroller but when I debug it's always null.
Bean
#ManagedBean
#ViewScoped
// ??? #RequestScoped
public class BoekingController {
#Inject
private ZoekService zoekService;
#Inject
private BetaalwijzeService betaalwijzeService;
#EJB
private transient BoekingService boekingService;
#ManagedProperty("#{sessionController}")
private SessionController sessionController;
public void init() {
if (betaalwijzeId > 0) {
betaalwijze = betaalwijzeService.findToegestandBetaalwijze(betaalwijzeId);
}
reis = zoekService.findReis(reisId);
if (aantalPersonen > 0) {
instellenBoeking(aantalPersonen, betaalwijze, new Klant(1, "Test", "test#test.be", "test"), reis);
}
}
As you can see I have hardcoded the object myself and persistence works, I just can't get the variable from the sessionController posted below.
SessionController
#SessionScoped
#Named(value = "sessionController")
public class SessionController implements Serializable{
Klant klant;
public Klant getKlant() {
return klant;
}
public void setKlant(Klant klant) {
this.klant = klant;
}
On pages I can access the sessionobject by using:#{sessionController.klantNaam}
The annotation ManagedProperty, as explained in the linked javadoc, should be used to inject a JSF bean annotated with ManagedBean.
Use Inject annotation for injecting a CDI bean.

#PostConstruct Interceptor with #Named #ViewScoped not invoked

I have read carefully the article about Interceptors in the Seam/Weld documentation and implemented a InterceptorBinding:
#InterceptorBinding
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.METHOD, ElementType.TYPE})
public #interface MyLog {}
and a Interceptor class:
#MyLog #Interceptor
public class ErpLogInterceptor implements Serializable
{
#AroundInvoke
public Object logMethodEntry(InvocationContext invocationContext) throws Exception
{..}
#PostConstruct
public Object logPostConstruct(InvocationContext invocationContext) throws Exception
{...}
}
No I tried to activated the interceptor in the #Named #ViewScoped bean:
#javax.inject.Named;
#javax.faces.bean.ViewScoped
public class MyBean implements Serializable
{
#PostConstruct #MyLog
public void init()
{...}
#MyLog public void toggleButton()
{..}
}
If I push a button on my JSF page the method toggleButton is invoked correctly and the Interceptor method logMethodEntry is called. But it seems the method #PostConstruct (I am interested in) is never intercepted by my class.
The question seems to be related to Java EE Interceptors and #ViewScoped bean but actually my interceptor is working in normal methods.
You should set return type of #PostConstruct interceptor to void not Object.
Change:
#PostConstruct
public Object logPostConstruct(InvocationContext invocationContext) throws Exception
{...}
to:
#PostConstruct
public void logPostConstruct(InvocationContext invocationContext) throws Exception
{...}

Categories