spring-cloud-gateway icon indicating copy to clipboard operation
spring-cloud-gateway copied to clipboard

Support running the gateway with other reactive containers besides netty

Open muzuro opened this issue 7 years ago • 66 comments

I am trying to use tomcat instead netty. To achive this i have excluded netty from dependencies and included tomcat, so my build.gradle dependecies:

dependencies {
    compile (group: 'org.springframework.cloud', name: 'spring-cloud-starter-gateway', version: '2.0.0.M4') {
        exclude group: 'org.springframework.boot', module: 'spring-boot-starter-netty'
    }
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-tomcat', version: '2.0.0.M7'
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-webflux'
}

Hower it is not enough, i get ClassCastException:

java.lang.ClassCastException: org.springframework.core.io.buffer.DefaultDataBufferFactory cannot be cast to org.springframework.core.io.buffer.NettyDataBufferFactory
	at org.springframework.cloud.gateway.filter.NettyWriteResponseFilter.lambda$filter$0(NettyWriteResponseFilter.java:61) ~[spring-cloud-gateway-core-2.0.0.M4.jar:2.0.0.M4]
	at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:44) ~[reactor-core-3.1.1.RELEASE.jar:3.1.1.RELEASE]
	at reactor.core.publisher.Mono.subscribe(Mono.java:2913) ~[reactor-core-3.1.1.RELEASE.jar:3.1.1.RELEASE]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:167) ~[reactor-core-3.1.1.RELEASE.jar:3.1.1.RELEASE]

Is it possible to use tomcat with gateway instead netty? Thanks!

muzuro avatar Dec 27 '17 11:12 muzuro

Not currently.

spencergibb avatar Jan 08 '18 21:01 spencergibb

I already have code for this that just needs to be formalized. The difficulty will be running all the tests with other containers.

spencergibb avatar Jan 08 '18 21:01 spencergibb

@spencergibb can u provide code ?

grku2opia avatar Jan 18 '18 20:01 grku2opia

@spencergibb How is the progress now? Thank you

ghost avatar Feb 02 '18 12:02 ghost

None so far

spencergibb avatar Feb 02 '18 12:02 spencergibb

Hi, I am also facing the same issue and the error is as below

java.lang.ClassCastException: org.springframework.core.io.buffer.DefaultDataBufferFactory cannot be cast to org.springframework.core.io.buffer.NettyDataBufferFactory at org.springframework.cloud.gateway.filter.NettyWriteResponseFilter.lambda$filter$0(NettyWriteResponseFilter.java:61) ~[spring-cloud-gateway-core-2.0.0.BUILD-SNAPSHOT.jar:2.0.0.BUILD-SNAPSHOT]

ghoddg avatar Feb 14 '18 06:02 ghoddg

@ghoddg this is likely not going to happen in 2.0.0. For now you have to use netty.

spencergibb avatar Feb 14 '18 15:02 spencergibb

Hi @spencergibb .. I am starting my api gateway service with tomcat. The service is started properly but when i hit api, it is giving me the above error

Also, my requirement is that I want to deploy it on weblogic as war and then also it should work is it possible?

ghoddg avatar Feb 14 '18 17:02 ghoddg

No

spencergibb avatar Feb 14 '18 17:02 spencergibb

@spencergibb Thanks for update.

ghoddg avatar Feb 14 '18 17:02 ghoddg

@spencergibb , from above communication, i got understanding that, API Gateway Service with Spring Cloud Gateway will not work with Tomcat as well as Weblogic for now and it will work only with netty. is my understanding correct?

ghoddg avatar Feb 14 '18 17:02 ghoddg

Hello, I have a similar problem without Tomcat nor Jetty in classpath. The error I am getting is the following:

java.lang.ClassCastException: org.springframework.core.io.buffer.DefaultDataBufferFactory cannot be cast to org.springframework.core.io.buffer.NettyDataBufferFactory
	at org.springframework.cloud.gateway.filter.NettyWriteResponseFilter.lambda$filter$0(NettyWriteResponseFilter.java:61) ~[spring-cloud-gateway-core-2.0.0.M6.jar:2.0.0.M6]
	at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:44) ~[reactor-core-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at reactor.core.publisher.Mono.subscribe(Mono.java:3006) ~[reactor-core-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:167) ~[reactor-core-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.ignoreDone(MonoIgnoreThen.java:185) ~[reactor-core-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreInner.onComplete(MonoIgnoreThen.java:234) ~[reactor-core-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:245) ~[reactor-core-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:130) ~[reactor-core-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at reactor.core.publisher.FluxRetryPredicate$RetryPredicateSubscriber.onComplete(FluxRetryPredicate.java:107) ~[reactor-core-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at reactor.core.publisher.MonoCreate$DefaultMonoSink.success(MonoCreate.java:140) ~[reactor-core-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at reactor.ipc.netty.channel.PooledClientContextHandler.fireContextActive(PooledClientContextHandler.java:84) ~[reactor-netty-0.7.3.RELEASE.jar:0.7.3.RELEASE]
	at reactor.ipc.netty.http.client.HttpClientOperations.onInboundNext(HttpClientOperations.java:551) ~[reactor-netty-0.7.3.RELEASE.jar:0.7.3.RELEASE]
	at reactor.ipc.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:134) ~[reactor-netty-0.7.3.RELEASE.jar:0.7.3.RELEASE]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) ~[netty-transport-4.1.20.Final.jar:4.1.20.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) ~[netty-transport-4.1.20.Final.jar:4.1.20.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) ~[netty-transport-4.1.20.Final.jar:4.1.20.Final]
	at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:438) ~[netty-transport-4.1.20.Final.jar:4.1.20.Final]
	at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:310) ~[netty-codec-4.1.20.Final.jar:4.1.20.Final]
	at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:297) ~[netty-codec-4.1.20.Final.jar:4.1.20.Final]
	at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:413) ~[netty-codec-4.1.20.Final.jar:4.1.20.Final]
	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:265) ~[netty-codec-4.1.20.Final.jar:4.1.20.Final]
	at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:253) ~[netty-transport-4.1.20.Final.jar:4.1.20.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) ~[netty-transport-4.1.20.Final.jar:4.1.20.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) ~[netty-transport-4.1.20.Final.jar:4.1.20.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) ~[netty-transport-4.1.20.Final.jar:4.1.20.Final]
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1412) ~[netty-transport-4.1.20.Final.jar:4.1.20.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) ~[netty-transport-4.1.20.Final.jar:4.1.20.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) ~[netty-transport-4.1.20.Final.jar:4.1.20.Final]
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:943) ~[netty-transport-4.1.20.Final.jar:4.1.20.Final]
	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:141) ~[netty-transport-4.1.20.Final.jar:4.1.20.Final]
	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:645) ~[netty-transport-4.1.20.Final.jar:4.1.20.Final]
	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:580) ~[netty-transport-4.1.20.Final.jar:4.1.20.Final]
	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:497) ~[netty-transport-4.1.20.Final.jar:4.1.20.Final]
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:459) ~[netty-transport-4.1.20.Final.jar:4.1.20.Final]
	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:886) ~[netty-common-4.1.20.Final.jar:4.1.20.Final]
	at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_151]

Is there another dependency that could cause this problem?

My Spring boot 2.0.0.RC1 dependencies are the following:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.session</groupId>
	<artifactId>spring-session-core</artifactId>
</dependency>
<dependency>
	<groupId>com.hazelcast</groupId>
	<artifactId>hazelcast</artifactId>
</dependency>

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-test</artifactId>
	<scope>test</scope>
</dependency>
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-contract-wiremock</artifactId>
</dependency>
<dependency>
	<groupId>io.projectreactor</groupId>
	<artifactId>reactor-test</artifactId>
	<scope>test</scope>
</dependency>

dharezlak avatar Feb 16 '18 08:02 dharezlak

I just noticed that this error occurs only in the testing mode. When run normally the gateway forwarding works fine.

dharezlak avatar Feb 19 '18 09:02 dharezlak

Another thing I noticed is that when I use WebClient in tests instead of WebTestClient all is fine. Should using WebTestClient in spring-gateway based applications be prohibited?

dharezlak avatar Feb 19 '18 13:02 dharezlak

It's not. It is used to test the gateway

spencergibb avatar Feb 19 '18 13:02 spencergibb

@spencergibb It is indeed. The source of my problem was using the @AutoConfigureWebTestClient annotation. Without it my tests are working fine. When I use it I get the ClassCastException mentioned earlier. Do you think this calls for a separate issue?

dharezlak avatar Feb 20 '18 09:02 dharezlak

are u open to pr's for tomcat support? for 2.0 or 2.1

drdamour avatar Feb 22 '18 22:02 drdamour

@drdamour I already have code https://github.com/spring-cloud/spring-cloud-gateway/issues/145#issuecomment-358772643. The trouble is testing everything.

spencergibb avatar Feb 22 '18 22:02 spencergibb

yeah i assumed you meant unit test and thus PR.

what type of testing are you referring to then?

drdamour avatar Feb 22 '18 22:02 drdamour

Basically all the integration tests. Anything that spins up a container then makes real network calls thru the gateway.

spencergibb avatar Feb 22 '18 23:02 spencergibb

k...how are you hoping to structure the tests...duality for every netty test have a tomcat test. or just abstract away the backing implementation in all the tests?

or is there some prior art you are looking to follow?

drdamour avatar Feb 22 '18 23:02 drdamour

My guess is rerunning all the tests with some system properties. Copied tests is prohibitive. Most have a base class already.

spencergibb avatar Feb 22 '18 23:02 spencergibb

how will that work with your maven circle build? just 2+ surefire/failsafe executions?

drdamour avatar Feb 22 '18 23:02 drdamour

jenkins is our canonical build

spencergibb avatar Feb 22 '18 23:02 spencergibb

ok doesn't change anything right? still just calls maven goals (i'm assuming) and i'm guessing you want to test all reactive containers supported on each build?

drdamour avatar Feb 22 '18 23:02 drdamour

There's another problem of including tomcat, jetty etc...

spencergibb avatar Feb 22 '18 23:02 spencergibb

def could make the netty container the default profile and have other profiles that bring in the others & exclude netty..but the build couldn't be done as one command AFAIK (don't think you can switch profiles/classpaths with extra executions of surefire or failsafe). Never tried though..maybe. could do the tests as other modules..but that'd either mean sharing a test jar from core or copy paste tests over.

good problem...

drdamour avatar Feb 23 '18 00:02 drdamour

Maybe you can try to cancel the dependency ---providedRuntime('org.springframework.boot:spring-boot-starter-tomcat')

ghost avatar May 28 '18 02:05 ghost

I am also facing the same issue and i do not want to migrate my services from tomcat to netty. Any idea, when can we expect the fix?

SachinSharmaa avatar Dec 29 '18 07:12 SachinSharmaa