Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: return immidiately if VaadinSession is not initialized (#11974) #11986

Merged
merged 1 commit into from
Oct 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -175,16 +175,25 @@ public void valueBound(HttpSessionBindingEvent arg0) {
*/
@Override
public void valueUnbound(HttpSessionBindingEvent event) {
// If we are going to be unbound from the session, the session must be
// closing
// Notify the service
if (service == null) {
// The Vaadin session instance may be not yet initialized properly via
// {@link #refreshTransients(WrappedSession, VaadinService)}. It happens
// when the session is deserialized and container decides that it's
// expired. Such session is not known to anyone (except deserializer)
// and nothins should be done with it: just return immediately.
//
// Be aware that not initialized session doesn't have the
// correct/expected state: it has no lock, service, session, etc.
if (!isInitialized()) {
getLogger().warn(
"A VaadinSession instance not associated to any service is getting unbound. "
+ "Session destroy events will not be fired and UIs in the session will not get detached. "
+ "This might happen if a session is deserialized but never used before it expires.");
} else if (VaadinService.getCurrentRequest() != null
&& getCurrent() == this) {
return;
}
// If we are going to be unbound from the session, the session must be
// closing
// Notify the service
if (VaadinService.getCurrentRequest() != null && getCurrent() == this) {
checkHasLock();
// Ignore if the session is being moved to a different backing
// session or if GAEVaadinServlet is doing its normal cleanup.
Expand Down Expand Up @@ -632,8 +641,10 @@ public void removeUI(UI ui) {
* <code>Lock</code> interface than {@link Lock#lock()} and
* {@link Lock#unlock()}.
*
* @return the <code>Lock</code> that is used for synchronization, never
* <code>null</code>
* @return the <code>Lock</code> that is used for synchronization, it's
* never <code>null</code> for the session which is in use, i.e. if
* {@link #refreshTransients(WrappedSession, VaadinService)} has
* been called for it
* @see #lock()
* @see Lock
*/
Expand Down Expand Up @@ -1116,4 +1127,22 @@ public StreamResourceRegistry getResourceRegistry() {
public String getCsrfToken() {
return csrfToken;
}

/**
* Checks whether the session is properly initialized/in use.
* <p>
* The session is initialized if
* {@link #refreshTransients(WrappedSession, VaadinService)} has been called
* for it. If the session is just created or deserialized but not yet in
* real use then it's not initialized and it's state is incomplete.
*
* @return whether the session is initialized
*/
private boolean isInitialized() {
boolean isInitialized = service != null;
assert isInitialized
|| session == null : "The wrapped session must be null if the service is null (which happens after deserialization)";
return isInitialized;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -483,4 +483,24 @@ protected Lock getSessionLock(WrappedSession wrappedSession) {
Assert.assertNull(vaadinSession.getSession());
}

@Test
public void valueUnbound_sessionIsNotInitialized_noAnyInteractions() {
VaadinSession session = Mockito.spy(TestVaadinSession.class);

HttpSessionBindingEvent event = Mockito
.mock(HttpSessionBindingEvent.class);
session.valueUnbound(null);

Mockito.verify(session).valueUnbound(null);
Mockito.verifyNoInteractions(event);
Mockito.verifyNoMoreInteractions(session);
}

public static class TestVaadinSession extends VaadinSession {

public TestVaadinSession() {
super(null);
}
}

}