GWT + Spring Boot @Autowired无法正常工作

时间:2018-08-16 10:23:25

标签: java spring spring-boot gwt

我已经在GWT + Spring Boot中创建了一个应用程序,当我尝试使用@Autowired时-得到NullPointerException。显然@Autowired不起作用,并且没有在正确的位置插入Bean。我该如何解决这种情况?

调度传入的RPC调用时发生异常

  

com.google.gwt.user.server.rpc.UnexpectedException:服务方法   '公共抽象java.util.List   com.myGWT.springbootapp.client.UserService.list()引发了意外   异常:java.lang.NullPointerException

文件web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <servlet>
        <servlet-name>userService</servlet-name>
        <servlet-class>com.myGWT.springbootapp.server.UserServiceImpl</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>userService</servlet-name>
        <url-pattern>/gwtApp/service</url-pattern>
    </servlet-mapping>


    <welcome-file-list>
        <welcome-file>GWTApp.html</welcome-file>
    </welcome-file-list>
</web-app>

pom.xml

<name>spring-boot-app</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->

    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <gwt.version>2.7.0</gwt.version>
    </properties>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.8</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.8</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.apache.logging.log4j</groupId>
                    <artifactId>log4j-api</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>


        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc6</artifactId>
            <version>11.2.0.4</version>
        </dependency>

        <!-- GWT -->
        <dependency>
            <groupId>com.google.gwt</groupId>
            <artifactId>gwt-user</artifactId>
            <version>${gwt.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.google.gwt</groupId>
            <artifactId>gwt-servlet</artifactId>
            <version>${gwt.version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>com.google.gwt</groupId>
            <artifactId>gwt-codeserver</artifactId>
            <version>${gwt.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.google.gwt</groupId>
            <artifactId>gwt-dev</artifactId>
            <version>${gwt.version}</version>
            <scope>provided</scope>
            <exclusions>
            <exclusion>
                <artifactId>apache-jsp</artifactId>
                <groupId>org.eclipse.jetty</groupId>
            </exclusion>
            </exclusions>
        </dependency>
    </dependencies>



    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>gwt-maven-plugin</artifactId>
                    <version>${gwt.version}</version>
                </plugin>
                <plugin>
                    <artifactId>maven-war-plugin</artifactId>
                    <version>2.5</version>
                </plugin>
                <plugin>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>2.4.1</version>
                </plugin>
            </plugins>
        </pluginManagement>
        <plugins>
            <plugin>
                <artifactId>maven-clean-plugin</artifactId>
                <configuration>
                    <filesets>
                        <fileset>
                            <directory>target</directory>
                        </fileset>
                        <fileset>
                            <directory>builds</directory>
                            <includes>
                                <include>**/*.*</include>
                            </includes>
                        </fileset>
                    </filesets>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.2</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-source-plugin</artifactId>
                <version>2.4</version>
                <executions>
                    <execution>
                        <id>attach-sources</id>
                        <phase>deploy</phase>
                        <goals>
                            <goal>jar-no-fork</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <artifactId>maven-deploy-plugin</artifactId>
                <version>2.8.2</version>
                <executions>
                    <execution>
                        <id>deploy</id>
                        <phase>deploy</phase>
                        <goals><goal>deploy</goal></goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

文件UserServiceImpl.java

package com.myGWT.springbootapp.server;

import com.myGWT.springbootapp.client.UserService;
import com.myGWT.springbootapp.entities.User;
import com.myGWT.springbootapp.repositories.UserRepository;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserServiceImpl extends RemoteServiceServlet implements UserService {

AnnotationConfigWebApplicationContext();

    @Autowired
    private UserRepository repository ;

    @Override
    public List<User> list() {
        return repository.findAll();
    }
}

文件UserRepository.java

package com.myGWT.springbootapp.repositories;


import com.myGWT.springbootapp.entities.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

import java.util.List;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {

}

文件UserService.java

package com.myGWT.springbootapp.client;

import com.myGWT.springbootapp.entities.User;
import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;


import java.util.List;

@RemoteServiceRelativePath("service")
public interface UserService extends RemoteService {

  List<User> list();
}

文件GWTApp.java

package com.myGWT.springbootapp.client;

import com.myGWT.springbootapp.entities.User;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.TextColumn;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.*;
import com.google.gwt.view.client.ListDataProvider;

import java.util.List;

public class GWTApp implements EntryPoint {

    private  UserServiceAsync userService = GWT.create(UserService.class);

    private ListDataProvider<User> createTable (CellTable<User> table){
        TextColumn<User> idColumn =new TextColumn<User>() {
            @Override
            public String getValue(User object) {
                return object.getId().toString();
            }
        };
        TextColumn<User> loginColumn =new TextColumn<User>() {
            @Override
            public String getValue(User object) {
                return object.getLogin();
            }
        };
        table.addColumn(idColumn, "Id");
        table.addColumn(loginColumn, "Login");
        final ListDataProvider<User> dataProvider = new ListDataProvider<>();
        dataProvider.addDataDisplay(table);
        this.userService.list(new AsyncCallback<List<User>>() {
            @Override
            public void onFailure(Throwable caught) {
                Window.alert("Error: " + caught.getMessage());
            }

            @Override
            public void onSuccess(List<User> result) {
                dataProvider.getList().addAll(result);

            }
        });
        return dataProvider;
    }

    public void onModuleLoad() {
        CellTable<User> table = new CellTable<>();
        ListDataProvider<User> dataProvider = createTable(table);

        RootPanel.get().add(table);
    }
}

项目的目录结构

enter image description here

1 个答案:

答案 0 :(得分:1)

简短的答案是:Spring并未实例化您的GWT服务;因此它无法自动将任何东西连接到其中。

Jetty容器实际上负责创建和映射UserServiceImpl的实例。这就是您的web.xml所描述的。

您的@Service注解确实在Spring上下文中创建了一个Servlet实例,正如您所期望的那样,但Jetty并不知道。历史上,我已从基于RemoteServiceServlet的服务中删除了@Service批注,并添加了以下方法来提供@Autowire支持:

public class UserServiceImpl extends RemoteServiceServlet implements UserService {

...

     @Override
     public void init() throws ServletException {
          super.init();
          SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, getServletContext());
     }

...

}

来自SpringBeanAutowiringSupport javadoc

  

根据存储在ServletContext中的当前根Web应用程序上下文,对给定目标对象进行@Autowired注入。

在Servlet创建和繁荣期间,Jetty会调用init(),真是令人难以置信。这是很棘手的事情,因为它桥接了两个不相关的流程,但目前在生产中对我有用。

使用兼容Servlet 3.0+的容器,您可能可以找到一种方法来使用WebApplicationInitializerjavadoc)来AnnotationConfigWebApplicationContextjavadoc)来启动Spring上下文。映射到servlet,这将允许您从那里使用实例(这取代了web.xml)。

编辑:

由于您使用的是Spring Boot,因此可以看一下该线程,该线程显示了如何通过ServletRegistrationBeanHow can I register a secondary servlet with Spring Boot?映射servlet(请参阅checketts的答案)