session issue

Hi,

I developed vaadin 7 project. Used Tomcat 7 as a server. Application runs fine in a single machine. But when I tried to run the same application in another machine at the same time connected to LAN. I get Exception as below.

java.lang.IllegalStateException: Cannot remove from parent when the session is not locked. Furthermore, there is another locked session, indicating that the component might be about to be moved from one session to another.
at com.vaadin.ui.AbstractSingleComponentContainer.removeFromParent(AbstractSingleComponentContainer.java:164)
at com.vaadin.ui.AbstractComponentContainer.addComponent(AbstractComponentContainer.java:212)
at com.vaadin.ui.AbsoluteLayout.addComponent(AbsoluteLayout.java:151)
at com.vaadin.ui.AbsoluteLayout.addComponent(AbsoluteLayout.java:128)

Please help me to resolve.

Thanks
Sakthivel

I would guess that you are sharing a component between users. This typically happens if you store the component in a static field somewhere; as a rule, you really shouldn’t have anything static in Vaadin applications. Check that first, and report back please.

Hi Thomas,

       Thank you so much for your response. I have double checked my code, I dont have any static reference to any fields or components. Please suggest.

Thanks,
Sakthi

Well, that exception says that you are moving a component from one session (UI) and trying to add it to another session (UI). Vaadin tries to remove it from the old session, but fails (as it should). Somewhere you are using an old component from a previous session inside a new session; the stacktrace should point out exactly where that happens.

Super. Thank you. I cleared this issue.

Hi Sakthiplan,

I am facing a similar issue, can you explain the solution for this issue?

Thanks.

I experienced that issue as well. I am using Spring to manage dependencies. One of the dependencies is the menu that is autowired inside of UI. Turns out that I forgot to add the proper scope annotation on the menu, which means (I guess) is that it is global by default. After adding @UIScope the issue was gone.

@SpringComponent
@UIScope
public class DashboardMenu extends CustomComponent {

    public DashboardMenu() {
        setPrimaryStyleName("valo-menu");
        setSizeUndefined();
        setCompositionRoot(buildContent());
    }

    // more members here
}

Pavel, yes, you are correct. UIScope and ViewScope are the correct scopes when dealing with components, both in Spring and CDI. If you use bigger scopes then there is a big chance the same component will end up in two UIs, producing the error above.

@Sakthiplan Vel: Could you tell me please how to resolve it? I just can’t find any solution, it’s frustrating…

Achim, could you provide more details on your issue please? maybe I can help.

Hi Thomas, I try to automate some tests in Google Chrome (Version 48.0.2564.97 m).

My code is the following

package testsuite;

import java.io.File;
import java.util.NoSuchElementException;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.interactions.Mouse;
import com.vaadin.testbench.By;
import com.vaadin.testbench.TestBench;
import com.vaadin.testbench.TestBenchTestCase;

public class Zugriff extends TestBenchTestCase {

private static WebDriver driver;
private static Actions act;

@BeforeClass
static public void setUpClass() {
    File file = new File("chromedriver.exe");
    System.setProperty("webdriver.chrome.driver", file.getAbsolutePath().replace("\\", "\\\\"));
    driver = TestBench.createDriver(new ChromeDriver());
    act = new Actions(driver);
}

@Before
public void setUp() {
setDriver(driver);
}

@After
public void tearDown() {
driver.quit();
}

@Test // fertig
public void BenutzerzugriffZurückTaste() throws InterruptedException {
driver.get(“http://localhost:8080/<I can’t post the remaining URL because of company internal information>”);
loginUser(“a”, “a”);
findElement(By.id(“mail_tool”));
Thread.sleep(3000);
logoutUser();
driver.navigate().back();
Thread.sleep(3000);
act.click(findElement(
By.xpath(“//[@id="abc-860345546"]
/div/div[2]
/div/div/div/div/div/div/div[1]
/input")))
.perform();
´}
@Test // fertig
public void BenutzerzugriffFalschesPasswort() throws InterruptedException {
driver.get(“http://localhost:8080/<I can’t post the remaining URL because of company internal information>);
loginUser(“aaa”, “zzz”);
act.click(findElement(By.xpath(”//
[@id="M2TableauToolbox-860345546-overlays"]
/div[2]
/div/div/h1”)))
.perform();
}
}

In my Eclipse I commented out the @After mehtod because it causes the error (after reopening the browser) you can see in the attached picture.

22926.png

I use Java 8 in an Eclipse “Java EE IDE for Web Developers”.Version: Mars.1 Release (4.5.1)

Our Application Server at the moment is Wildfly 10 but we’ll change to Tomcat soon.

I’m pretty sure the error has nothing to do with your test; if you click on the same element in a deployed app, you should get the same error. It’s the same thing as above; something in your code is trying to share a Vaadin component between multiple users. Are you using CDI or Spring injections, by any chance?

Ok, that’s interesting. I mailed to our developers who wrote/write the application. I wait for the answer eagerly.

when i test my application with 2 session, in one browser all things is OK and in another one i get exception.

 @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
 @PreserveOnRefresh
@SpringComponent
 public class TestUI extends UI {
  @Autowired
  MainLayout content;
  @Autowired
  DetailView detailView;
 @Override
 protected void init(VaadinRequest request) {
  VaadinSession.setCurrent(VaadinSession.getCurrent());
  Navigator navigator = new Navigator(this, detailView);
  navigator.addView("tests", TestView.class);
  setContent(content);
  }
}

java.lang.IllegalStateException: Cannot remove from parent when the session is not locked. Furthermore, there is another locked session, indicating that the component might be about to be moved from one session to another. at com.vaadin.ui.AbstractSingleComponentContainer.removeFromParent(AbstractSingleComponentContainer.java:175) at com.vaadin.ui.AbstractSingleComponentContainer.setContent(AbstractSingleComponentContainer.java:148) at com.vaadin.ui.UI.setContent(UI.java:1312)

did u fix this?

Let’s clarify scope first.
order by existance time.

singleton > UI scope > view scope > prototype scope. You can inject in this order, but not reverse!

If you follow a simple rule, create all vaadin ui component, like layout, button etc in prototype scope, You should never face “Cannot remove from parent” problem.

But how to use prototyp scoped layout in your view? You cannot inject prototype instance into view instance.
Inject applicationContext!
then add a method to component that return component self to setup component. code below is in vaadinview.

​tableController = applicationContext.getBean(TableController.class).afterInjection(eventBus, bgs); And this is the method that return TableController self:

    public TableController afterInjection(EventBus eventBus, ButtonGroup...btnGroups) {
        this.eventBus = eventBus;
        this.eventBus.register(this);
        addStyleName("table-controller");
        setWidth("100%");
        addComponent(menu.afterInjection(eventBus, btnGroups));
        
        setComponentAlignment(menu, Alignment.MIDDLE_LEFT);
        trashBt = new Button(messageSource.getMessage("tablecontroller.trashswitcher", null, UI.getCurrent().getLocale()), FontAwesome.TRASH);
        
        trashBt.addClickListener(new ClickListener() {
            @Override
            public void buttonClick(ClickEvent event) {
                String styles = event.getButton().getStyleName();
                if (StyleUtil.hasStyleName(styles, ValoTheme.BUTTON_PRIMARY)) {
                    eventBus.post(new TrashedCheckBoxEvent(false));
                } else {
                    eventBus.post(new TrashedCheckBoxEvent(true));
                }
            }
        });
         HorizontalLayout hl = new HorizontalLayout();
        hl.setSpacing(true);
        hl.addComponent(trashBt);
        hl.addComponent(pager.afterInjection(eventBus));
        addComponent(hl);
        hl.setComponentAlignment(trashBt, Alignment.MIDDLE_RIGHT);
        setComponentAlignment(hl, Alignment.MIDDLE_RIGHT);
        return this;
    }

I think those problem is not about vaadin, But about spring. You shoud understand spring first.