Unexpected Behavior with RoutesDSL

79 views
Skip to first unread message

thorn...@gmail.com

unread,
Jan 7, 2017, 7:08:57 PM1/7/17
to Play Framework
Hi everybody! 

I have come across some weird behavior with the RoutingDSL closing down the database connection pool, and think it's a bug - code sample attched as a JUnit test.

My application.conf file is pretty much stock, with the exception of enabling the H2 in memory database. I found this error when I was trying to use Ebean and JPA to control my database. 

Here is the full error:

[info] application - Creating Pool for datasource 'default'
[info] play.api.Play - Application started (Dev)
[info] p.c.s.NettyServer - Listening for HTTP on /0:0:0:0:0:0:0:0:59280
[info] application - Shutting down connection pool.

javax.persistence.PersistenceException: java.sql.SQLException: HikariDataSource HikariDataSource (HikariPool-0) has been closed.

at com.avaje.ebeaninternal.server.transaction.TransactionManager.createTransaction(TransactionManager.java:285)
at com.avaje.ebeaninternal.server.core.DefaultServer.createServerTransaction(DefaultServer.java:2064)
at com.avaje.ebeaninternal.server.core.BeanRequest.createImplicitTransIfRequired(BeanRequest.java:45)
at com.avaje.ebeaninternal.server.core.PersistRequestBean.initTransIfRequiredWithBatchCascade(PersistRequestBean.java:181)
at com.avaje.ebeaninternal.server.persist.DefaultPersister.insert(DefaultPersister.java:398)
at com.avaje.ebeaninternal.server.persist.DefaultPersister.save(DefaultPersister.java:387)
at com.avaje.ebeaninternal.server.core.DefaultServer.save(DefaultServer.java:1482)
at com.avaje.ebeaninternal.server.core.DefaultServer.save(DefaultServer.java:1475)
at com.avaje.ebean.Model.save(Model.java:232)
at models.User.create(User.java:52)
at scrapers.RoutingDSLTest.testDBConnection(RoutingDSLTest.java:62)
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:498)
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.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
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.JUnitForkedStarter.main(JUnitForkedStarter.java:41)
Caused by: java.sql.SQLException: HikariDataSource HikariDataSource (HikariPool-0) has been closed.
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:79)
at org.jdbcdslog.DataSourceProxyBase.getConnection(DataSourceProxyBase.java:45)
at play.db.ebean.DefaultEbeanConfig$EbeanConfigParser$WrappingDatasource.getConnection(DefaultEbeanConfig.java:149)
at com.avaje.ebeaninternal.server.transaction.TransactionManager.createTransaction(TransactionManager.java:262)
... 33 more


Here is how you can reproduce this: 

import com.typesafe.config.ConfigFactory;
import models.User;
import org.junit.Test;
import play.*;
import play.inject.guice.GuiceApplicationBuilder;
import play.libs.ws.WSClient;
import play.routing.RoutingDsl;
import play.server.Server;
import play.test.WithApplication;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static play.mvc.Results.ok;

public class RoutingDSLTest extends WithApplication{

    @Override
    protected Application provideApplication() {

        Application application = new GuiceApplicationBuilder() //ran with the stock H2 in memory db
                .in(Mode.TEST)
                .build();

        return application;
    }

    /**
     * Usually errors out with HikariDataSource-0 has been closed
     */
    @Test
    public void testDBConnection() throws Exception {
        Server server = Server.forRouter(new RoutingDsl()
                        .GET("/hello/:to").routeTo(to ->
                                ok("Hello " + to)
                        )
                        .build(),
                Mode.DEV
        );
        WSClient ws = WS.newClient(server.httpPort());

        User.create("name", "email", "password"); //Can be replaced with any Ebean model

        String request = ws.url("/hello/world").get().toCompletableFuture().get().getUri().toString();

        assertNotNull(User.find.byId(1L));
    }

}

Let me know if you need any more info. 

- Jevin

Greg Methvin

unread,
Jan 10, 2017, 2:03:46 AM1/10/17
to play-framework
You're using WithApplication and you're also using Server.forRouter, which itself creates a new application. So when you start the second app inside testDBConnection, it's running the stop hooks for the first (since only one app can be run at once).

--
You received this message because you are subscribed to the Google Groups "Play Framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framework+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/play-framework/7e17d5a5-2c82-4cc9-9663-a86b79bbcbae%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Greg Methvin
Tech Lead - Play Framework

Jevin G

unread,
Jan 10, 2017, 4:13:06 PM1/10/17
to Play Framework
Ah. What's the proper way to test a database application against a web service with the Play Framework if we cannot create a secondary mock web service? 

- Jevin

To unsubscribe from this group and stop receiving emails from it, send an email to play-framewor...@googlegroups.com.

Greg Methvin

unread,
Jan 10, 2017, 5:40:29 PM1/10/17
to play-framework
It seems like in the example you provided you just want to remove WithApplication. The server you created will start its own application. Not sure if you're talking about the code above or some other testing case.

I agree it would be useful to be able to start multiple applications at once. In Play 2.6 we will support this out of the box, but at the moment there are still a few non-deprecated APIs (and numerous deprecated APIs) where we use the static application instance, so allowing multiple apps to run at once could cause unexpected problems.

Technically this limitation is already possible to work around by writing your own helper to start the server, similar to what we already have here, but without Play.start: https://github.com/playframework/playframework/blob/master/framework/src/play-server/src/main/scala/play/core/server/Server.scala#L224. For a mock server this might be appropriate. But you will need at least one application started as your "main" app for anything that uses global state.

Greg

To unsubscribe from this group and stop receiving emails from it, send an email to play-framework+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/play-framework/3c8127d6-2119-4019-aa1d-d2bf0e68ae89%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Jevin G

unread,
Jan 12, 2017, 10:40:26 AM1/12/17
to Play Framework
Is there a Java version of this I could take a look at?

 - Jevin

Greg Methvin

unread,
Jan 12, 2017, 4:58:44 PM1/12/17
to play-framework
If you're referring to the code I linked, then there is no Java API. That's a helper we use for the Java version of Server.forRouter.

To unsubscribe from this group and stop receiving emails from it, send an email to play-framework+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/play-framework/c052e40f-4d85-4c17-af06-7b8bdba8bb1b%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages