Giter VIP home page Giter VIP logo

Comments (6)

jxblum avatar jxblum commented on May 8, 2024

This "problem" is caused by Apache Geode itself (!), in version 1.9.

SBDG 1.2 is based on Spring Boot 2.2, where both SBDG 1.2 and Spring Boot 2.2 are based on SD[G] Moore/2.2, which is based on Apache Geode 1.9.0 (currently).

Apache Geode 1.9 transitively pulls in the javax.servlet:javax.servlet-api given that it declares a compile-time dependency on org.eclipse.jetty:jetty-server:

$ gradlew :spring-geode:dependencies | less
...
     +--- org.apache.geode:geode-core:1.9.0
     |    +--- com.github.stephenc.findbugs:findbugs-annotations:1.3.9-1
     |    +--- org.jgroups:jgroups:3.6.14.Final
     |    +--- antlr:antlr:2.7.7
...
     |    +--- org.eclipse.jetty:jetty-server:9.4.12.v20180830 -> 9.4.19.v20190610
     |    |    +--- javax.servlet:javax.servlet-api:3.1.0 -> 4.0.1
     |    |    +--- org.eclipse.jetty:jetty-http:9.4.19.v20190610
     |    |    |    +--- org.eclipse.jetty:jetty-util:9.4.19.v20190610
     |    |    |    \--- org.eclipse.jetty:jetty-io:9.4.19.v20190610
     |    |    |         \--- org.eclipse.jetty:jetty-util:9.4.19.v20190610
     |    |    \--- org.eclipse.jetty:jetty-io:9.4.19.v20190610 (*)

from spring-boot-data-geode.

jxblum avatar jxblum commented on May 8, 2024

SBDG cannot add an exclusion on org.eclipse.jetty:jetty-server in the starters since this will cause an Exception on shutdown of an Apache Geode/Pivotal GemFire (client or peer) cache instance...

2019-08-21 00:44:32.819  WARN 63204 --- [m shutdown hook] o.a.g.d.i.InternalDistributedSystem      : Exception trying to close cache

java.lang.BootstrapMethodError: java.lang.IllegalAccessError: no such method: org.apache.geode.internal.cache.HttpService.stop()void/invokeVirtual
    at org.apache.geode.internal.cache.GemFireCacheImpl.close(GemFireCacheImpl.java:2183) ~[geode-core-1.9.0.jar:na]
    at org.apache.geode.distributed.internal.InternalDistributedSystem.disconnect(InternalDistributedSystem.java:1627) [geode-core-1.9.0.jar:na]
    at org.apache.geode.distributed.internal.InternalDistributedSystem.lambda$static$4(InternalDistributedSystem.java:2278) [geode-core-1.9.0.jar:na]
    at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_192]
Caused by: java.lang.IllegalAccessError: no such method: org.apache.geode.internal.cache.HttpService.stop()void/invokeVirtual
    at java.lang.invoke.MethodHandleNatives.linkMethodHandleConstant(MethodHandleNatives.java:483) ~[na:1.8.0_192]
    ... 4 common frames omitted
Caused by: java.lang.NoClassDefFoundError: org/eclipse/jetty/server/Handler
    at java.lang.invoke.MethodHandleNatives.resolve(Native Method) ~[na:1.8.0_192]
    at java.lang.invoke.MemberName$Factory.resolve(MemberName.java:975) ~[na:1.8.0_192]
    at java.lang.invoke.MemberName$Factory.resolveOrFail(MemberName.java:1000) ~[na:1.8.0_192]
    at java.lang.invoke.MethodHandles$Lookup.resolveOrFail(MethodHandles.java:1394) ~[na:1.8.0_192]
    at java.lang.invoke.MethodHandles$Lookup.linkMethodHandleConstant(MethodHandles.java:1750) ~[na:1.8.0_192]
    at java.lang.invoke.MethodHandleNatives.linkMethodHandleConstant(MethodHandleNatives.java:477) ~[na:1.8.0_192]
    ... 4 common frames omitted
Caused by: java.lang.ClassNotFoundException: org.eclipse.jetty.server.Handler
    at java.net.URLClassLoader.findClass(URLClassLoader.java:382) ~[na:1.8.0_192]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_192]
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349) ~[na:1.8.0_192]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_192]
    ... 10 common frames omitted

Therefore, it is unclear to me whether the Apache Geode node shuts down cleanly under these circumstances.

As such, I strongly recommend that the Apache Geode community fix this issues by:

  1. Making the Eclipse Jetty dependency "optional" in Apache Geode core (i.e. geode-core), and...
  2. Not expect or require the user to have to declare the Eclipse Jetty dependency on the application classpath, and...
  3. Ensure that an Apache Geode cache instance is shutdown properly when Eclipse Jetty is not on the classpath.

Jetty is only used by Apache Geode Locator/Managers and Servers to implement the embedded HTTP service, which hosts the Developer REST API, and Management (Admin) REST API and/or Pulse, respectively.

Jetty is never needed and used on the client-side of a GemFire/Geode cache node (e.g. ClientCache instance), which makes the problem noted in the previous comment even worse (!) since SBDG focuses on auto-configuring a ClientCache instance, by default!

from spring-boot-data-geode.

jxblum avatar jxblum commented on May 8, 2024

Given the information above, I have filed GEODE-7107 to resolve this "Apache Geode problem" properly, where it belongs!

from spring-boot-data-geode.

jxblum avatar jxblum commented on May 8, 2024

I see that GEODE-7107 is already in progress for including a fix.

See comment for more details.

from spring-boot-data-geode.

jxblum avatar jxblum commented on May 8, 2024

After review, it turns out the comment referencing the commit is not a fix!

See the followup comment for further details.

from spring-boot-data-geode.

jxblum avatar jxblum commented on May 8, 2024

To recap the problem:

  1. First, when a Spring Boot project using Apache Geode is created with Spring Initializer, it currently declares the following SBDG starter dependency for you:
<dependency>
    <groupId>org.springframework.geode</groupId>
    <artifactId>spring-geode-starter</artifactId>
    <version>1.2.0.BUILD-SNAPSHOT</version>
</dependency>

If you try to run the provided app, you will hit an Exception:

org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:156) ~[spring-boot-2.2.0.M5.jar:2.2.0.M5]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) ~[spring-context-5.2.0.RC1.jar:5.2.0.RC1]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141) ~[spring-boot-2.2.0.M5.jar:2.2.0.M5]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:746) [spring-boot-2.2.0.M5.jar:2.2.0.M5]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:396) [spring-boot-2.2.0.M5.jar:2.2.0.M5]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) [spring-boot-2.2.0.M5.jar:2.2.0.M5]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1225) [spring-boot-2.2.0.M5.jar:2.2.0.M5]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1214) [spring-boot-2.2.0.M5.jar:2.2.0.M5]
    at org.example.app.springgeodeapp.SpringGeodeAppApplication.main(SpringGeodeAppApplication.java:10) [classes/:na]
Caused by: org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.getWebServerFactory(ServletWebServerApplicationContext.java:203) ~[spring-boot-2.2.0.M5.jar:2.2.0.M5]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:179) ~[spring-boot-2.2.0.M5.jar:2.2.0.M5]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:153) ~[spring-boot-2.2.0.M5.jar:2.2.0.M5]
    ... 8 common frames omitted

This is because geode-core pulls in jetty-server, which pulls in the javax.servlet-api:

$ gradlew :spring-geode:dependencies | less
...
     +--- org.apache.geode:geode-core:1.9.0
     |    +--- com.github.stephenc.findbugs:findbugs-annotations:1.3.9-1
     |    +--- org.jgroups:jgroups:3.6.14.Final
     |    +--- antlr:antlr:2.7.7
...
     |    +--- org.eclipse.jetty:jetty-server:9.4.12.v20180830 -> 9.4.19.v20190610
     |    |    +--- javax.servlet:javax.servlet-api:3.1.0 -> 4.0.1
     |    |    +--- org.eclipse.jetty:jetty-http:9.4.19.v20190610
     |    |    |    +--- org.eclipse.jetty:jetty-util:9.4.19.v20190610
     |    |    |    \--- org.eclipse.jetty:jetty-io:9.4.19.v20190610
     |    |    |         \--- org.eclipse.jetty:jetty-util:9.4.19.v20190610
     |    |    \--- org.eclipse.jetty:jetty-io:9.4.19.v20190610 (*)

As I stated already, Jetty should be an "optional" dependency in Apache Geode since 1) it is server-side specific (Locators, Managers and Servers) in order to implement the embedded HTTP service that hosts the Developer/Management REST APIs and Pulse, and 2) Jetty is simply not required to properly run a Locator, Manager or Server since starting the embedded HTTP service is optional.

  1. However, if I try to only "exclude" the Jetty dependency from the SBDG starter:
<dependency>
   <groupId>org.springframework.geode</groupId>
   <artifactId>spring-geode-starter</artifactId>
   <version>1.2.0.BUILD-SNAPSHOT</version>
   <exclusions>
      <exclusion>
         <groupId>org.eclipse.jetty</groupId>
         <artifactId>jetty-server</artifactId>
      </exclusion>
   </exclusions>
</dependency>

NOTE: Previously, I incorrectly thought I needed to exclude the org.springframework:spring-web dependency as well, because I thought that spring-web also caused Spring Boot to determine the application was a "Web application" when spring-web was on the application classpath. However, this thinking was incorrect, as @snicole pointed out, because it is only the presence of the javax.servlet-api that causes Spring Boot to decide that the application is a Web application, thereby causing an embedded Servlet Container to be bootstrapped by Spring Boot on application startup. As an additional side note, spring-web already appropriately marks the javax.servlet-api dependency as "optional", so spring-web cannot cause this issue. Only Apache Geode is causing this issue!

However, the exclude on jetty-server leads to the following Exception when the Apache Geode cache instance (client or peer) is shutdown:

java.lang.BootstrapMethodError: java.lang.IllegalAccessError: no such method: org.apache.geode.internal.cache.HttpService.stop()void/invokeVirtual
    at org.apache.geode.internal.cache.GemFireCacheImpl.close(GemFireCacheImpl.java:2183) ~[geode-core-1.9.0.jar:na]
    at org.apache.geode.distributed.internal.InternalDistributedSystem.disconnect(InternalDistributedSystem.java:1627) [geode-core-1.9.0.jar:na]
    at org.apache.geode.distributed.internal.InternalDistributedSystem.lambda$static$4(InternalDistributedSystem.java:2278) [geode-core-1.9.0.jar:na]
    at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_192]
Caused by: java.lang.IllegalAccessError: no such method: org.apache.geode.internal.cache.HttpService.stop()void/invokeVirtual
    at java.lang.invoke.MethodHandleNatives.linkMethodHandleConstant(MethodHandleNatives.java:483) ~[na:1.8.0_192]
    ... 4 common frames omitted
Caused by: java.lang.NoClassDefFoundError: org/eclipse/jetty/server/Handler
    at java.lang.invoke.MethodHandleNatives.resolve(Native Method) ~[na:1.8.0_192]
    at java.lang.invoke.MemberName$Factory.resolve(MemberName.java:975) ~[na:1.8.0_192]
    at java.lang.invoke.MemberName$Factory.resolveOrFail(MemberName.java:1000) ~[na:1.8.0_192]
    at java.lang.invoke.MethodHandles$Lookup.resolveOrFail(MethodHandles.java:1394) ~[na:1.8.0_192]
    at java.lang.invoke.MethodHandles$Lookup.linkMethodHandleConstant(MethodHandles.java:1750) ~[na:1.8.0_192]
    at java.lang.invoke.MethodHandleNatives.linkMethodHandleConstant(MethodHandleNatives.java:477) ~[na:1.8.0_192]
    ... 4 common frames omitted
Caused by: java.lang.ClassNotFoundException: org.eclipse.jetty.server.Handler
    at java.net.URLClassLoader.findClass(URLClassLoader.java:382) ~[na:1.8.0_192]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_192]
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349) ~[na:1.8.0_192]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_192]
    ... 10 common frames omitted
  1. Finally, I tried simply excluding the transitive dependency, javax.servlet:javax.servlet-api from SBDG's spring-geode-starter, and Lo and behold, that app starts and shuts down successfully!
<dependency>
   <groupId>org.springframework.geode</groupId>
   <artifactId>spring-geode-starter</artifactId>
   <version>1.2.0.BUILD-SNAPSHOT</version>
   <exclusions>
      <exclusion>
         <groupId>javax.servlet</groupId>
         <artifactId>javax.servlet-api</artifactId>
      </exclusion>
   </exclusions>
</dependency>

This exclusion does not seem to present any problems for an Apache Geode cache on shutdown, either. \o/

As such, the targeted (temporary/workaround) fix for this Issue will be to include an exclusion on the javax.servlet:javax.servlet-api in the SBDG starters, at least until GEODE-7107 is properly addressed!

from spring-boot-data-geode.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.