heroku将spring app从java 7升级到java 8遇到java.util.Map$Entry无法解决问题

问题描述

我正在尝试在 heroku 上将 spring mvc 应用程序从 java 7 升级到 8 我的设置如下:

pom.xml

 <?xml version="1.0" encoding="UTF-8"?>
    <project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>spring-hibernate-template</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <org.springframework.version>3.1.1.RELEASE</org.springframework.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.0.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>3.2.13.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>3.2.13.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>org.hsqldb</groupId>
            <artifactId>hsqldb</artifactId>
            <version>2.2.8</version>
        </dependency>
        <dependency>
          <groupId>org.postgresql</groupId>
          <artifactId>postgresql</artifactId>
          <version>42.2.1</version>
        </dependency>
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.4</version>
        </dependency>               
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>3.6.10.Final</version>
        </dependency>
        <dependency>
            <groupId>com.github.jsimone</groupId>
            <artifactId>webapp-runner</artifactId>
            <version>7.0.34.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-core-asl</artifactId>
            <version>1.9.2</version>
        </dependency>
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-mapper-asl</artifactId>
            <version>1.9.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tiles</groupId>
            <artifactId>tiles-extras</artifactId>
            <version>3.0.1</version>
        </dependency>
        <dependency>
            <groupId>com.newrelic.agent.java</groupId>
            <artifactId>newrelic-agent</artifactId>
            <version>3.9.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
            <version>3.2.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
            <version>3.2.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security.oauth</groupId>
            <artifactId>spring-security-oauth2</artifactId>
            <version>1.0.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>com.dropBox.core</groupId>
            <artifactId>dropBox-core-sdk</artifactId>
            <version>3.1.3</version>
        </dependency>
        <dependency>
            <groupId>com.turo</groupId>
            <artifactId>pushy</artifactId>
            <version>0.12.0</version>
        </dependency>
          <!--<dependency>-->
             <!--<groupId>com.notnoop.apns</groupId>-->
             <!--<artifactId>apns</artifactId>-->
             <!--<version>1.0.0.Beta6</version>-->
        <!--</dependency>-->
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.2</version>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.4</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>copy</goal>
                        </goals>
                        <configuration>
                            <artifactItems>
                                <artifactItem>
                                    <groupId>com.github.jsimone</groupId>
                                    <artifactId>webapp-runner</artifactId>
                                    <version>7.0.34.0</version>
                                    <destFileName>webapp-runner.jar</destFileName>
                                </artifactItem>
                            </artifactItems>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.6</version>
                <executions>
                    <execution>
                          <id>copy-new-relic</id>
                          <phase>package</phase>
                     <goals>
                            <goal>copy-dependencies</goal>
                      </goals>
                      <configuration>
                            <includeGroupIds>com.newrelic.agent.java</includeGroupIds>
                            <includeArtifactIds>newrelic-agent</includeArtifactIds>
                            <stripVersion>true</stripVersion>
                      </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

system.properties:

java.runtime.version=1.8

在/WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>

Spring-Hibernate-模板

<welcome-file-list>
    <welcome-file>/WEB-INF/jsp/index.jsp</welcome-file>
</welcome-file-list>

<session-config>
    <session-timeout>-1</session-timeout>
</session-config>

<!-- Creates the Spring Container shared by all Servlets and Filters -->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/rest-dispatcher-servlet.xml
        /WEB-INF/rest-dispatcher-servlet-security.xml
    </param-value>
</context-param>

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<servlet>
    <servlet-name>rest-dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.dispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>rest-dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

<error-page>
    <error-code>404</error-code>
    <location>/WEB-INF/jsp/error404.jsp</location>
</error-page>
<error-page>
    <error-code>405</error-code>
    <location>/WEB-INF/jsp/error500.jsp</location>
</error-page>
<error-page>
    <error-code>500</error-code>
    <location>/WEB-INF/jsp/error500.jsp</location>
</error-page>
<error-page>
    <error-code>503</error-code>
    <location>/WEB-INF/jsp/error500.jsp</location>
</error-page>

最后是我的 spring 配置 xml (dispatcher-servlet.xml)

<?xml  version="1.0" encoding="UTF-8"?>

<context:annotation-config />
<context:component-scan base-package="com.myproject" />

<mvc:annotation-driven/>

<bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
    <property name="prefix" value="/WEB-INF/jsp/" />
    <property name="suffix" value=".jsp" />
</bean>

<bean id="jspViewResolverForBusiness" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
    <property name="prefix" value="/WEB-INF/jsp/business/" />
    <property name="suffix" value=".jsp" />
</bean>

<mvc:resources location="/resources/" mapping="/resources/**"></mvc:resources>

<!-- Task excutor -->
<bean id="taskExecutor"
    class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
    <property name="corePoolSize" value="5" />
    <property name="maxPoolSize" value="10" />
    <property name="WaitForTasksToCompleteOnShutdown" value="true" />
</bean>

<!-- Tiles configuration -->
<bean id="tilesviewResolver" class="org.springframework.web.servlet.view.tiles3.TilesViewResolver"/>
<bean id="tilesConfigurer"
    class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">
    <property name="deFinitions">
        <list>
            <value>/WEB-INF/tiles/tiles-deFinitions.xml</value>
        </list>
    </property>
</bean>

<tx:annotation-driven />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
    <property name="dataSource" ref="dataSource"/>

</bean>

<beans profile="default">
    <jdbc:embedded-database id="dataSource"/>        
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerfactorybean">
        <property name="dataSource" ref="dataSource"/>
        <property name="jpavendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpavendorAdapter"/>
        </property>
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.HsqlDialect</prop>
                <prop key="hibernate.hbm2ddl.auto">create</prop>
            </props>
        </property>
    </bean>
</beans>

<beans profile="prod">
    <bean class="java.net.URI" id="dbUrl">
        <constructor-arg value="#{systemEnvironment['DATABASE_URL']}"/>
    </bean>

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="url" value="#{ 'jdbc:postgresql://' + @dbUrl.getHost() + ':' + @dbUrl.getPort() + @dbUrl.getPath() + '?sslmode=require' }"/>
        <property name="username" value="#{ @dbUrl.getUserInfo().split(':')[0] }"/>
        <property name="password" value="#{ @dbUrl.getUserInfo().split(':')[1] }"/>
    </bean>
    
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerfactorybean">
        <property name="dataSource" ref="dataSource"/>
        <property name="jpavendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpavendorAdapter"/>
        </property>
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.PostgresqlDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <!-- change this to 'verify' before running as a production app -->
                <prop key="hibernate.hbm2ddl.auto">update</prop>
            </props>
        </property>
    </bean>
</beans>

我可以确认应用程序的某些部分运行良好,例如一些安静的 json 端点(它们确实响应正确的 json 数据) 但是任何 JSP 页面渲染都死了......错误日志看起来像这样:

:在

java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
2021-03-14T18:07:52.329301+00:00 app[web.1]: at java.lang.Thread.run(Thread.java:748)
2021-03-14T18:07:52.329302+00:00 app[web.1]:
2021-03-14T18:07:52.369622+00:00 app[web.1]: Mar 14,2021 6:07:52 PM org.apache.jasper.compiler.JDTCompiler$1 findType
2021-03-14T18:07:52.369623+00:00 app[web.1]: SEVERE: Compilation error
2021-03-14T18:07:52.369624+00:00 app[web.1]: org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException
2021-03-14T18:07:52.369625+00:00 app[web.1]: at org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader.<init>(ClassFileReader.java:372)
2021-03-14T18:07:52.369625+00:00 app[web.1]: at org.apache.jasper.compiler.JDTCompiler$1.findType(JDTCompiler.java:231)
2021-03-14T18:07:52.369626+00:00 app[web.1]: at org.apache.jasper.compiler.JDTCompiler$1.findType(JDTCompiler.java:187)
2021-03-14T18:07:52.369626+00:00 app[web.1]: at org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment.askForType(LookupEnvironment.java:113)
2021-03-14T18:07:52.369629+00:00 app[web.1]: at org.eclipse.jdt.internal.compiler.lookup.UnresolvedReferenceBinding.resolve(UnresolvedReferenceBinding.java:49)
2021-03-14T18:07:52.369630+00:00 app[web.1]: at org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.resolveType(BinaryTypeBinding.java:122)

]: at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1653)
2021-03-14T18:07:52.369644+00:00 app[web.1]: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
2021-03-14T18:07:52.369644+00:00 app[web.1]: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
2021-03-14T18:07:52.369644+00:00 app[web.1]: at java.lang.Thread.run(Thread.java:748)
2021-03-14T18:07:52.369645+00:00 app[web.1]:
2021-03-14T18:07:52.518809+00:00 app[web.1]: Mar 14,2021 6:07:52 PM org.apache.catalina.core.StandardWrapperValve invoke
2021-03-14T18:07:52.518811+00:00 app[web.1]: SEVERE: Servlet.service() for servlet [jsp] in context with path [/] threw exception [Unable to compile class for JSP:
2021-03-14T18:07:52.518812+00:00 app[web.1]:
2021-03-14T18:07:52.518813+00:00 app[web.1]: An error occurred at line: 1 in the generated java file
2021-03-14T18:07:52.518813+00:00 app[web.1]: The type java.util.Map$Entry cannot be resolved. It is indirectly referenced from required .class files
2021-03-14T18:07:52.518814+00:00 app[web.1]:
2021-03-14T18:07:52.518814+00:00 app[web.1]: An error occurred at line: 1 in the generated java file
2021-03-14T18:07:52.518815+00:00 app[web.1]: The type java.io.ObjectInputStream cannot be resolved. It is indirectly referenced from required .class files
2021-03-14T18:07:52.518815+00:00 app[web.1]:
2021-03-14T18:07:52.518816+00:00 app[web.1]: Stacktrace:] with root cause
2021-03-14T18:07:52.518816+00:00 app[web.1]: org.apache.jasper.JasperException: Unable to compile class for JSP:
2021-03-14T18:07:52.518816+00:00 app[web.1]:
2021-03-14T18:07:52.518817+00:00 app[web.1]: An error occurred at line: 1 in the generated java file
2021-03-14T18:07:52.518818+00:00 app[web.1]: The type java.util.Map$Entry cannot be resolved. It is indirectly referenced from required .class files
2021-03-14T18:07:52.518818+00:00 app[web.1]:
2021-03-14T18:07:52.518818+00:00 app[web.1]: An error occurred at line: 1 in the generated java file
2021-03-14T18:07:52.518819+00:00 app[web.1]: The type java.io.ObjectInputStream cannot be resolved. It is indirectly referenced from required .class files
2021-03-14T18:07:52.518819+00:00 app[web.1]:
2021-03-14T18:07:52.518820+00:00 app[web.1]: Stacktrace:
2021-03-14T18:07:52.518820+00:00 app[web.1]: at org.apache.jasper.compiler.DefaultErrorHandler.javacError(DefaultErrorHandler.java:102)
2021-03-14T18:07:52.518821+00:00 app[web.1]: at org.apache.jasper.compiler.Errordispatcher.javacError(Errordispatcher.java:331)
2021-03-14T18:07:52.518821+00:00 app[web.1]: at org.apache.jasper.compiler.JDTCompiler.generateClass(JDTCompiler.java:468)
2021-03-14T18:07:52.518822+00:00 app[web.1]: at org.apache.jasper.compiler.Compiler.compile(Compiler.java:378)
2021-03-14T18:07:52.518822+00:00 app[web.1]: at org.apache.jasper.compiler.Compiler.compile(Compiler.java:353)
2021-03-14T18:07:52.518822+00:00 app[web.1]: at org.apache.jasper.compiler.Compiler.compile(Compiler.java:340)
2021-03-14T18:07:52.518823+00:00 app[web.1]: at org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:646)

]: at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004)
2021-03-14T18:07:52.518832+00:00 app[web.1]: at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
2021-03-14T18:07:52.518832+00:00 app[web.1]: at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1653)
2021-03-14T18:07:52.518832+00:00 app[web.1]: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
2021-03-14T18:07:52.518833+00:00 app[web.1]: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
2021-03-14T18:07:52.518833+00:00 app[web.1]: at java.lang.Thread.run(Thread.java:748)
2021-03-14T18:07:52.518834+00:00 app[web.1]:
2021-03-14T18:07:52.720440+00:00 app[web.1]: Mar 14,2021 6:07:52 PM org.apache.jasper.compiler.JDTCompiler$1 findType
2021-03-14T18:07:52.720458+00:00 app[web.1]: SEVERE: Compilation error
2021-03-14T18:07:52.720459+00:00 app[web.1]: org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException
2021-03-14T18:07:52.720459+00:00 app[web.1]: at org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader.<init>(ClassFileReader.java:372)
2021-03-14T18:07:52.720460+00:00 app[web.1]: at org.apache.jasper.compiler.JDTCompiler$1.findType(JDTCompiler.java:231)
2021-03-14T18:07:52.720460+00:00 app[web.1]: at org.apache.jasper.compiler.JDTCompiler$1.findType(JDTCompiler.java:187)
2021-03-14T18:07:52.720461+00:00 app[web.1]: at org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment.askForType(LookupEnvironment.java:113)

: at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
2021-03-14T18:07:52.720498+00:00 app[web.1]: at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1653)
2021-03-14T18:07:52.720499+00:00 app[web.1]: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
2021-03-14T18:07:52.720499+00:00 app[web.1]: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
2021-03-14T18:07:52.720500+00:00 app[web.1]: at java.lang.Thread.run(Thread.java:748)
2021-03-14T18:07:52.720500+00:00 app[web.1]:
2021-03-14T18:07:52.808532+00:00 app[web.1]: Mar 14,2021 6:07:52 PM org.apache.jasper.compiler.JDTCompiler$1 findType
2021-03-14T18:07:52.808535+00:00 app[web.1]: SEVERE: Compilation error
2021-03-14T18:07:52.808535+00:00 app[web.1]: org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException
2021-03-14T18:07:52.808536+00:00 app[web.1]: at org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader.<init>(ClassFileReader.java:372)
2021-03-14T18:07:52.808537+00:00 app[web.1]: at org.apache.jasper.compiler.JDTCompiler$1.findType(JDTCompiler.java:231)
2021-03-14T18:07:52.808537+00:00 app[web.1]: at org.apache.jasper.compiler.JDTCompiler$1.findType(JDTCompiler.java:187)
2021-03-14T18:07:52.808538+00:00 app[web.1]: at org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment.askForType(LookupEnvironment.java:113)
2021-03-14T18:07:52.808539+00:00 app[web.1]: at org.eclipse.jdt.internal.compiler.lookup.UnresolvedReferenceBinding.resolve(UnresolvedReferenceBinding.java:49)
2021-03-14T18:07:52.808540+00:00 app[web.1]: at org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.resolveType(BinaryTypeBinding.java:122)
2021-03-14T18:07:52.808540+00:00 app[web.1]: at org.eclipse.jdt.internal.compiler.lookup.PackageBinding.getTypeOrPackage(PackageBinding.java:168)

所以我认为这与 java 8 env 问题有关?但是在heroku上,我相信tomcat的版本认是9 https://devcenter.heroku.com/changelog-items/1724 但我不知道如何使用 heroku cli 实际检查我的 tomcat 版本,有人知道吗?

或者看起来像heroku tomcat问题?如果是这样,我应该使用哪个版本的 tomcat? 请指教 谢谢

解决方法

能否请您尝试将 web-runner 依赖项升级到 9.0.27.1?目前设置为,

       <dependency>
            <groupId>com.github.jsimone</groupId>
            <artifactId>webapp-runner</artifactId>
            <version>7.0.34.0</version>
            <scope>provided</scope>
        </dependency>