StardogAuthenticationException when running up a new embedded server after shutting down a previous one

Hi,

We have some tests that use the embedded server and with Stardog 5.0 we are getting this exception:

com.complexible.stardog.security.StardogAuthenticationException: Authentication failed for account 'admin'

	at com.complexible.stardog.StardogKernel.login(StardogKernel.java:797)
	at com.complexible.stardog.api.EmbeddedDriver.lambda$login$21(EmbeddedDriver.java:155)
	at org.apache.shiro.subject.support.SubjectRunnable.doRun(SubjectRunnable.java:120)
	at org.apache.shiro.subject.support.SubjectRunnable.run(SubjectRunnable.java:108)
	at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:391)
	at com.complexible.stardog.api.EmbeddedDriver.login(EmbeddedDriver.java:154)
	at com.complexible.stardog.api.EmbeddedDriver.connectAdmin(EmbeddedDriver.java:185)
	at com.complexible.stardog.api.admin.AdminConnectionConfiguration.connect(AdminConnectionConfiguration.java:45)
	at no.difi.einnsyn.stardog.EmbeddedStardogDatabase.createDatabase(EmbeddedStardogDatabase.java:42)
	at no.difi.einnsyn.stardog.AbstractStardogServiceTest.beforeClass(AbstractStardogServiceTest.java:43)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
	at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
	at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:48)
	at org.junit.rules.RunRules.evaluate(RunRules.java:20)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runners.Suite.runChild(Suite.java:128)
	at org.junit.runners.Suite.runChild(Suite.java:27)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: org.apache.shiro.authc.AuthenticationException: Authentication failed for token submission [org.apache.shiro.authc.UsernamePasswordToken - admin, rememberMe=false].  Possible unexpected error? (Typical or expected login exceptions should extend from AuthenticationException).
	at org.apache.shiro.authc.AbstractAuthenticator.authenticate(AbstractAuthenticator.java:214)
	at org.apache.shiro.mgt.AuthenticatingSecurityManager.authenticate(AuthenticatingSecurityManager.java:106)
	at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:270)
	at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:256)
	at com.complexible.stardog.StardogKernel.login(StardogKernel.java:785)
	... 34 more
Caused by: java.lang.IllegalStateException: IndexConnection must be open.
	at com.google.common.base.Preconditions.checkState(Preconditions.java:173)
	at com.complexible.stardog.index.IndexConnectionImpl.assertOpen(IndexConnectionImpl.java:146)
	at com.complexible.stardog.index.IndexConnectionImpl.getReader(IndexConnectionImpl.java:82)
	at com.complexible.stardog.index.impl.DelegatingIndexConnection.getReader(DelegatingIndexConnection.java:94)
	at com.complexible.stardog.index.impl.DelegatingIndexConnection.getReader(DelegatingIndexConnection.java:94)
	at com.complexible.stardog.security.index.IndexPersistence.getResourceValue(IndexPersistence.java:128)
	at com.complexible.stardog.security.index.IndexAuthenticationManager.isUserEnabled(IndexAuthenticationManager.java:253)
	at com.complexible.stardog.security.impl.SystemSecurityManagerImpl.isUserEnabled(SystemSecurityManagerImpl.java:752)
	at com.complexible.stardog.security.index.IndexBackedSystemSecurityManager.isUserEnabled(IndexBackedSystemSecurityManager.java:400)
	at com.complexible.stardog.security.shiro.StardogRealm.authenticationInfo(StardogRealm.java:236)
	at com.complexible.stardog.security.shiro.StardogRealm.doGetAuthenticationInfo(StardogRealm.java:157)
	at org.apache.shiro.realm.AuthenticatingRealm.getAuthenticationInfo(AuthenticatingRealm.java:568)
	at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doSingleRealmAuthentication(ModularRealmAuthenticator.java:180)
	at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doAuthenticate(ModularRealmAuthenticator.java:267)
	at org.apache.shiro.authc.AbstractAuthenticator.authenticate(AbstractAuthenticator.java:198)
	... 38 more

Here is our code for running up the embedded server:

    protected static EmbeddedStardogDatabase stardogDatabase;
    protected static Stardog server;

    protected static final String LICENSE_KEY = "stardog-license-key.bin";

    @ClassRule
    public static TemporaryFolder systemFolder;

    @BeforeClass
    public static void beforeClass() throws Exception {
        systemFolder = new TemporaryFolder();
        systemFolder.create();

        FileUtils.copyFile(new File(LICENSE_KEY), new File(systemFolder.getRoot(), LICENSE_KEY));

        server = Stardog.builder()
                .home(systemFolder.getRoot())
                .create();


        stardogDatabase = new EmbeddedStardogDatabase();

        stardogDatabase.createDatabase();

        counts();


    }

    @AfterClass
    public static void tearDown() throws Exception {

        if(stardogDatabase != null){
            stardogDatabase.shutdown();
            stardogDatabase = null;
        }

        if (server != null) {
            server.shutdown();
            server = null;
        }
        systemFolder.delete();
    }
}

Each test passes if run on its own, but once you have two tests in two different classes and run these together, @BeforeClass for the second class will fail.

Is there a solution for this? This is the only bug stopping us from switching to 5.0 beta for our development since it breaks our unit tests.

I think I might have stumbled upon something here:

Looks like calling shutdown on Stardog server will shutdown something internally (seems to be the Kernel) so that calling server = Stardog.builder().home(systemFolder.getRoot()).create(); will not unshutdown Stardog. Looks like there is some injector code running that provides a shared Kernel object, and there is no way of getting a new one even after shutdown().

There’s not really an embedded server anymore; note what you’re creating is Stardog itself, not a server.

The embedded mode assumes there’s just a single embedded stardog+server at use per JVM whereas before an entire new stardog+server stack was being created.

We’ll look at ways we can relax that restriction. In the meantime, you can simply create one Stardog and use it for all of the tests, or you can spin up HTTP servers and use HTTP.

Thanks for the reply Michael.

What I’ve ended up with is just never calling shutdown(). This seems to work fine since I’m deleting the home directory anyway.

I have the same problem. If there are two test classes I get the same exception.

It seems stardog do not free the resources when calling Shutdown().

Then when calling the code below a second time, the test crashes.

STARDOG = Stardog.builder().home(homedir).create();

	try (AdminConnection aConn = AdminConnectionConfiguration.toEmbeddedServer()
			.credentials("admin", "admin")
			.connect()) {
		if (aConn.list().contains(DB)) {
			aConn.drop(DB);
		}

		aConn.createMemory(DB);
	} 

Any resolution for this?

If I’m understanding your code snippet correctly, you’re creating a new Stardog object each time. As I said in my earlier response, you cannot do that. Embedded mode operates under the assumption that there is a single instance of Stardog for the duration of the JVM.