Skip to content

Instantly share code, notes, and snippets.

@dwalend
Created September 18, 2018 20:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dwalend/9a0de4be870c1e253a5b2ad6597cde7b to your computer and use it in GitHub Desktop.
Save dwalend/9a0de4be870c1e253a5b2ad6597cde7b to your computer and use it in GitHub Desktop.
AsyncHttp4sServlet is not async
package net.shrine.api
import cats.effect.{ConcurrentEffect, IO}
import javax.servlet.annotation.WebListener
import javax.servlet.{ServletContextEvent, ServletContextListener}
import net.shrine.api.http4s.servlet.syntax.ShrineServletContextSyntax
import org.http4s.HttpRoutes
import org.http4s.dsl.impl.{->, /}
import org.http4s.dsl.io.{GET, Ok, Root, http4sOkSyntax}
import scala.concurrent.duration.DurationInt
import scala.language.higherKinds
import scala.concurrent.ExecutionContext.global
@WebListener
class Bootstrap extends ServletContextListener {
override def contextInitialized(sce: ServletContextEvent): Unit = {
val context = sce.getServletContext
implicit val concurrentEffect: ConcurrentEffect[IO] = IO.ioConcurrentEffect(IO.contextShift(global))
ShrineServletContextSyntax.mountService(
context = context,
name = "test http4s",
service = service,
asyncTimeout = 55.seconds
)
}
override def contextDestroyed(sce: ServletContextEvent): Unit = {}
val service: HttpRoutes[IO] = HttpRoutes.of[IO] {
case _@GET -> Root / "ping" => Ok("pong")
case _@GET -> Root / "parallel" =>
val startTime = System.currentTimeMillis()
scala.concurrent.blocking { Thread.sleep(15000) }
val endTime = System.currentTimeMillis()
val reply = s"blockingTestReq done in ${endTime - startTime}"
Ok(reply)
}
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>shrine-base</artifactId>
<groupId>net.shrine</groupId>
<version>1.26.2.1-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>test-app</artifactId>
<name>test http4s App</name>
<packaging>jar</packaging>
<build>
<plugins>
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.http4s</groupId>
<artifactId>http4s-dsl_${scala-major-version}</artifactId>
<version>0.19.0-M2</version>
</dependency>
<dependency>
<groupId>org.http4s</groupId>
<artifactId>http4s-core_${scala-major-version}</artifactId>
<version>0.19.0-M2</version>
</dependency>
<dependency>
<groupId>org.http4s</groupId>
<artifactId>http4s-server_${scala-major-version}</artifactId>
<version>0.19.0-M2</version>
</dependency>
<dependency>
<groupId>org.http4s</groupId>
<artifactId>http4s-servlet_${scala-major-version}</artifactId>
<version>0.19.0-M2</version>
</dependency>
<dependency>
<groupId>org.http4s</groupId>
<artifactId>http4s-circe_${scala-major-version}</artifactId>
<version>0.19.0-M2</version>
</dependency>
<dependency>
<groupId>org.http4s</groupId>
<artifactId>http4s-client_${scala-major-version}</artifactId>
<version>0.19.0-M2</version>
</dependency>
<dependency>
<groupId>org.http4s</groupId>
<artifactId>http4s-testing_${scala-major-version}</artifactId>
<version>0.19.0-M2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j-version}</version>
</dependency>
</dependencies>
</project>
package net.shrine.api.http4s.servlet.syntax
import cats.effect.{ConcurrentEffect, Effect}
import javax.servlet.{ServletContext, ServletRegistration}
import org.http4s.HttpRoutes
import org.http4s.server.DefaultServiceErrorHandler
import org.http4s.servlet.{AsyncHttp4sServlet, NonBlockingServletIo}
import scala.concurrent.duration.FiniteDuration
import scala.language.higherKinds
object ShrineServletContextSyntax {
/* This mountService function is a copy of the mountService function in org.http4s.servlet.syntax.ServletContextSyntax.scala
* version 0.18.9 of http4s with the asyncTimeout added as parameter so that the default timeout of 30 seconds can be modified
* There is a bug filed at https://github.com/http4s/http4s/issues/1812
*/
def mountService[F[_]: Effect](
context : ServletContext,
name: String,
service: HttpRoutes[F],
asyncTimeout: FiniteDuration,
mapping: String = "/*")(
implicit concurrentEffect: ConcurrentEffect[F]
): ServletRegistration.Dynamic = {
//todo this won't work because by default the service is BlockingIO val servlet = AsyncHttp4sServlet(service,asyncTimeout)
val servlet = new AsyncHttp4sServlet(
service = service,
asyncTimeout = asyncTimeout,
servletIo = NonBlockingServletIo(4096),
serviceErrorHandler = DefaultServiceErrorHandler[F]
)
val reg = context.addServlet(name, servlet)
reg.setLoadOnStartup(1)
reg.setAsyncSupported(true)
reg.addMapping(mapping)
reg
}
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>shrine-base</artifactId>
<groupId>net.shrine</groupId>
<version>1.26.2.1-SNAPSHOT</version>
<relativePath>/../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>test-war</artifactId>
<name>test http4s War</name>
<packaging>war</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<warName>test</warName>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>net.shrine</groupId>
<artifactId>test-app</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j-version}</version>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
<?xml version="1.0"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_4.dtd">
<web-app>
<listener>
<listener-class>net.shrine.api.Bootstrap</listener-class>
</listener>
</web-app>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment