un-scope #ViewAccessScoped Beans on Tab close - deltaspike

I have a JSF-App with two #ViewAccessScoped Beans and two Pages/Views, one Bean for a Search, on Bean for details. The details Bean references the #ViewAccessScoped so the data available when I go back to the Search. No other CDI-References. The WindowRenderMode is ClientWindowRenderMode.CLIENTWINDOW, no further configuration.
This works quite well so far. The Beans get un-scoped if i go to another page or logout. One Problem I Experienced:
When I open my details page in a new Browser tab, two new Beans are created, which is the expected Behavior. But when i close the tab, the Beans are still there. I guess the Server doesn't get notified when a tab get's closed.
Is there a built-in solution in deltaspike i can use to detect
tab clsoes?
Is there a Timeout for Beans with #ViewAccessScoped (beside the Session-Timeout)?
If there isn't a bulit-in solution: How can i programmatically un-scope my Beans? Preferably un-scope all Beans connected to that tab (=same Window-ID) (I'd detect the close my self with JavaScript and call a Bean-Method on close)

No, as it's not possible to catch a "tab close" event in JS.
See: javascript detect browser close tab/close browser
It was available in CODI but it was not migrated to DeltaSpike.
See: https://issues.apache.org/jira/browse/DELTASPIKE-437
You can do it via the WindowContext API:
#Inject private org.apache.deltaspike.core.spi.scope.window.WindowContext windowContext;
public void closeIt() {
windowContext.closeWindow("myWindowId");
}

Related

Spring.datasource.initialize=false not working

I am working on spring boot and batch application.
Due to batch, the application tries to connect to datasource
with spring-boot:run.
I want to stop that and tried spring.datasource.initialize=false
Along with this also put spring.batch.job.enabled=false
While the second one works fine, it seems the first one is ignored.
Could someone let me know if there is a way to stop db connection on startup?
Thanks in advance
The problem is, that spring/spring-boot loads the whole spring-context when it is "booted". This means, that all defined spring-beans are loaded into the spring-context during this boot-phase. In the case of spring-batch, this also means that the datasource bean is loaded and, if not turned off by "spring.batch.initializer.enabled=false", the spring-batch tables are initialized.
Generally, you cannot prevent this from happening as soon as you have added your spring-batch-starter to your maven dependencies.
Moreover, I don't understand why you want to prevent this from happening. It is just initialisation taking place and, provided that everything is configured correctly, this shouldn't be a problem at all.
Nonetheless, if you really want to stop the datasource from beeing initialized, you could try the following approach. However, I don't know if this will work.
Spring-Batch needs a datasource that is registered under the name "dataSource" in the spring-context. If no spring-bean with that name is found, it creates its own. But if you provide your own implementation/configuration for it, it will use your spring bean.
What you need to do is, to provide a proxy for a datasource that is loaded lazily and then register it under the name "dataSource" in the context:
#Configuration
public class MySetUp {
#Bean
public DataSource dataSource() {
// ... create your "lazy initializing" datasource
}
}
But - and let me stress that - this nothing that I would recommend and I don't see a good reason, why this should be necessary to do.
Furthermore, you mention that you only want load "initial static index page" (I assume, you are talking about html, right?). However, I don't see a "batch" use case, which should display html-pages. It would probably be better to have two different applications in this case.
Probably you could provide some more information about your use case.
As I understand, you don't want to prevent database connection during application startup.
Instead, you want to prevent execution of batch scripts.
Correct me, please, if I got it wrong.
To prevent execution of batch scripts set:
spring.batch.initializer.enabled=false

Spring Security 4 sessionRegistry doesn't populate Principal list

I am trying to implement a function where a admin user can terminate another user's session. I followed the official Spring Security documentation here: http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#list-authenticated-principals and started with getting all currently logged in users through sessionRegistry.getAllPrincipals(), but it always returned an empty list.
I set a breakpoint in SessionRegistryImpl.registerNewSession() and could see it did indeed get invoked and it did add the UserDetails (my own implementation with both equals() and hashCode() implemented) to the hashmap principals. But when I access sessionRegistry bean from a Spring MVC controller, the list is always empty.
My configuration looks pretty much the same as the documentation.
How to fix this? Did anyone successfully get SessionRegistry to work with Spring Security 4? I remember I made it work with Spring Security 3 by following these intructions(enter link description here)
OK, so I fixed the issue by cleaning up the Spring configuration files, as suggested by the comments. Someone messed up with the web.xml - he added a reference to the context XML that is already referenced by the Spring's DispatcherServlet, causing it to be loaded twice. He didn't know it, because Spring references the file implicitly.
P.S.
I learned my lessons, but 2 things the Spring folks could do better (maybe in Spring 5?):
There shouldn't be implicit context file loading. Currently, the framework will try to load the application context from a file named [servlet-name]-servlet.xml located in the application's WebContent/WEB-INF directory. Convention over configuration fails in this case.
There should be warning when a bean is loaded twice, if someone need to override a bean definition, he must declare explicitly. Otherwise it would take a lot of time to debug the kind of error this mistake will cause.

Spring annotation based configuration change

I have a spring MVC (3.1) web app using Hibernate that is all working correctly - today, I have tried to move the configuration completely over to annotation based config (only using xml for the security stuff that isnt yet supported by Spring in code config).
After some tuning I got the app starting with no errors and the home page loads correctly - however I am seeing some different behaviour with the Hibernate sessions - namely, I am getting the following error when loading a page that actually touches Hibernate entities:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.tmm.web.domain.Profile.connections, no session or session was closed
This is happening in the following scenario:
a request hits my #Controller and it loads the user Profile object
In the same method call (so we are not talking detached entities etc here) it tries to call profile.getConnections()
Profile.connections do not actually explicitly state a fetchtype, so should default to eager load (is my understanding?), but either way, the getConnections() call is directly after the loading of the profile - so would have thought even if it was being loaded lazily, it could easily just go back to the DB and load connections on demand.
//#Controller Code
Account viewedUser = accountService.loadAccountByUserName(userName);
model.put("viewedUserConnections", viewedUser.getUserProfile().getConnections());
//Profile Entity
#OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private List connections = new ArrayList();
Now, I know about lazy loading etc, so it's not a question about that - like i mentioned all the Hibernate stuff was working correctly - so really my question is, what Spring configuration might affect this behaviour?
I can post my before and after xml vs annotation config, but am hoping that someone can point me in the direction of some config that I might have missed in switching.
Your assumptions are mainly wrong:
In the same method call (so we are not talking detached entities etc here)
The method is a method of the controller. In typical Spring applications, controllers are not transactional, but services are. So, unless you configured an "open session in view" filter or interceptor, the session is closed when the transactional service method returns, and the controller thus always uses detached entities
Profile.connections do not actually explicitly state a fetchtype, so should default to eager load
No. XxxToMany associations are lazy by default.
If the same code worked before the transition, my guess is that you had an open session in view filter or interceptor, and that you forgot it when migrating to annotations.

JSF 'Tab' bean scope

I need create webapp with two pages and one backing bean for both pages. I tried #SessionScoped, but when I open other tab in a browser, I see the same data as in previous tab.
I tried to use MyFaces Orchestra, but backing bean is created on each AJAX request.
How to solve the problem?
Beforehand thankfull, Ilya
In a web browser if you open a new tab it will pass along the same session related cookies thus will be opend in the same session context. You need to open a new winodow to get a new session.

Using a Stateful Session Bean to track an user's session

it's my first question here and I hope that I'm doing it right.
I need to work on a Java EE project, so, before starting, I'm trying to do something simple and see if I can do that.
I'm stuck with Stateful Session Beans.
Here's the question :
How can I use a SFSB to track an user's session?
All the examples that I saw, ended up in "putting" the SFSB into a HttpSession attribute.
But I don't understand why!
I mean, if the bean is STATEFUL, why do I have to use the HttpSession to keep it?
Isn't an EJB Container's task to return the right SFSB to the client?
I've tried with a simple counter bean.
Without using the session, two different browsers have the same counter bean (clicking on "increment" changed the value for both of them).
Using session, I have two different values, each for every browser (clicking on "increment" on Firefox, added one just to Firefox's bean).
But my teacher told that a SFSB keeps the "conversational state with a client", so why it doesn't just work without using a HttpSession ?
If I understood correctly , isn't using HttpSession with a SFSB the same of doing it with a SLSB instead?
I hope that my question(s) is clear and that my English is not that poor!
EDIT :
I'm working on a login system.
Everything goes fine and after completing the login it takes me to a profile page that show user's data.
But reloading the page makes my data disappear!
I've tried adding HttpSession while logging but doing in this way makes the data stay even after the logout!
A Stateful Session Bean (SFSB) has to be combined with the HTTP session in a web environment, since it's a pure business bean that itself knows nothing about the web layer.
Traditionally EJBs even mandatory lived inside their own module (the EJB module), that couldn't even access web artifacts if they wanted to. This is an aspect of layered systems. See Packaging EJB in JavaEE 6 WAR vs EAR for more information about that.
The original clients for Stateful Session Beans were among others Swing desktop applications, that communicated with the remote EJB server via a binary protocol. A Swing application would obtain a connection to a remote Stateful Session Bean via a proxy/stub object. Embedded in this proxy is an ID of some kind that the server can associate with a specific SFSB. By holding on to this proxy object, the Swing client can make repeated calls to it and those will go to the same bean instance. This will thus create a session between the client and the server.
In the case of a web application, when a browser makes an initial request to a Java EE web application it gets a JSESSIONID that the server can associate with a specific HTTPSession instance. By holding on to this JSESSIONID, the browser can provide it with each followup request and this will activate the same http session server-side.
So, those concepts are very similar, but they do not automatically map to each other.
The browser only gets the JSESSIONID and has no knowledge about any SFSB ID. Unlike the Swing application, the browser communicates with web pages, not directly with Java beans.
For mapping the client's request to a specific stateful session bean, the EJB container only cares about the ID provided via the SFSB proxy. It can't see if the call happened to originate from code in the web module and can't/shouldn't really access any HTTP contexts.
The web layer being the client code that accesses the SFSB must 'hold on' to a specific proxy reference. Holding on to something in the web layer typically means storing it in the HTTP session.
There is however a bridge technology called CDI that can make this automatic connection. If you annotate your SFSB with CDI's #SessionScoped and obtain a reference to the SFSB via CDI (e.g. using #Inject), you don't have to manually put your SFSB into the http session. However, behind the scenes CDI will do exactly that anyway.
You need to define the bean with #SessionScoped instead of #RequestScoped (if you are looking for HttpSession equivalent solution)
something like
#SessionScoped
public class SessionInfo implements Serializable{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Have a look at following (explained in detail)
http://www.oracle.com/technetwork/articles/java/cdi-javaee-bien-225152.html

Resources