繁体   English   中英

Java REST API 发送 GET 请求时出错,但在 POST 上工作

[英]Java REST API Getting Error when sending GET Request, but works on POST

I have a REST API linked with a Java app that is connected to a database using JDBC that I am currently testing through the Swagger UI.

发送 post 请求完全正常,当给定类型的表为空时发送 GET 请求似乎也返回正常响应,但是一旦我在表中有数据时发送 GET 请求,我会收到以下错误。

GET /api/user 500 Server Error
java.lang.reflect.UndeclaredThrowableException: null
    at jdk.proxy2/jdk.proxy2.$Proxy16.getPersons(Unknown Source)
    at module.PersonModule.lambda$new$41b6884b$1(PersonModule.java:23)
    at io.jooby.internal.handler.DefaultHandler.apply(DefaultHandler.java:23)
    at io.jooby.internal.handler.WorkerHandler.lambda$apply$0(WorkerHandler.java:23)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.NoSuchMethodException: no such constructor: domain.Person.<init>()void/newInvokeSpecial
    at java.base/java.lang.invoke.MemberName.makeAccessException(MemberName.java:974)
    at java.base/java.lang.invoke.MemberName$Factory.resolveOrFail(MemberName.java:1117)
    at java.base/java.lang.invoke.MethodHandles$Lookup.resolveOrFail(MethodHandles.java:3649)
    at java.base/java.lang.invoke.MethodHandles$Lookup.findConstructor(MethodHandles.java:2750)
    at org.jdbi.v3.core.mapper.reflect.internal.BeanPropertiesFactory$BeanPojoProperties$PropertiesHolder.<init>(BeanPropertiesFactory.java:202)
    at org.jdbi.v3.core.config.JdbiCaches.lambda$declare$0(JdbiCaches.java:49)
    at org.jdbi.v3.core.config.JdbiCaches$1.lambda$get$1(JdbiCaches.java:63)
    at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1708)
    at org.jdbi.v3.core.config.JdbiCaches$1.get(JdbiCaches.java:63)
    at org.jdbi.v3.core.mapper.reflect.internal.BeanPropertiesFactory$BeanPojoProperties.getProperties(BeanPropertiesFactory.java:81)
    at org.jdbi.v3.core.mapper.reflect.internal.PojoMapper.specialize0(PojoMapper.java:99)
    at org.jdbi.v3.core.mapper.reflect.internal.PojoMapper.specialize(PojoMapper.java:80)
    at org.jdbi.v3.core.result.ResultSetResultIterator.<init>(ResultSetResultIterator.java:38)
    at org.jdbi.v3.core.result.ResultIterable.lambda$of$0(ResultIterable.java:54)
    at org.jdbi.v3.core.result.ResultIterable.stream(ResultIterable.java:228)
    at org.jdbi.v3.core.result.ResultIterable.collect(ResultIterable.java:284)
    at org.jdbi.v3.sqlobject.statement.internal.ResultReturner$CollectedResultReturner.mappedResult(ResultReturner.java:275)
    at org.jdbi.v3.sqlobject.statement.internal.SqlQueryHandler.lambda$configureReturner$0(SqlQueryHandler.java:61)
    at org.jdbi.v3.sqlobject.statement.internal.CustomizingStatementHandler.invoke(CustomizingStatementHandler.java:178)
    at org.jdbi.v3.sqlobject.statement.internal.SqlQueryHandler.invoke(SqlQueryHandler.java:27)
    at org.jdbi.v3.sqlobject.internal.SqlObjectInitData$1.lambda$invoke$0(SqlObjectInitData.java:132)
    at org.jdbi.v3.core.internal.Invocations.invokeWith(Invocations.java:44)
    at org.jdbi.v3.core.internal.Invocations.invokeWith(Invocations.java:26)
    at org.jdbi.v3.core.LazyHandleSupplier.lambda$invokeInContext$1(LazyHandleSupplier.java:77)
    at org.jdbi.v3.core.internal.Invocations.invokeWith(Invocations.java:44)
    at org.jdbi.v3.core.internal.Invocations.invokeWith(Invocations.java:26)
    at org.jdbi.v3.core.LazyHandleSupplier.invokeInContext(LazyHandleSupplier.java:76)
    at org.jdbi.v3.sqlobject.internal.SqlObjectInitData$1.call(SqlObjectInitData.java:138)
    at org.jdbi.v3.sqlobject.internal.SqlObjectInitData$1.invoke(SqlObjectInitData.java:132)
    at org.jdbi.v3.sqlobject.SqlObjectFactory.lambda$attach$2(SqlObjectFactory.java:110)
    at org.jdbi.v3.core.internal.OnDemandExtensions.lambda$invoke$5(OnDemandExtensions.java:98)
    at org.jdbi.v3.core.internal.exceptions.Unchecked.lambda$function$4(Unchecked.java:76)
    at org.jdbi.v3.core.internal.OnDemandExtensions.invoke(OnDemandExtensions.java:98)
    at org.jdbi.v3.core.internal.OnDemandExtensions.lambda$createProxy$2(OnDemandExtensions.java:82)
    at org.jdbi.v3.core.Jdbi.callWithExtension(Jdbi.java:476)
    at org.jdbi.v3.core.Jdbi.withExtension(Jdbi.java:463)
    at org.jdbi.v3.core.internal.OnDemandExtensions.lambda$createProxy$3(OnDemandExtensions.java:82)
    ... 8 common frames omitted
Caused by: java.lang.NoSuchMethodError: domain.Person: method 'void <init>()' not found
    at java.base/java.lang.invoke.MethodHandleNatives.resolve(Native Method)
    at java.base/java.lang.invoke.MemberName$Factory.resolve(MemberName.java:1085)
    at java.base/java.lang.invoke.MemberName$Factory.resolveOrFail(MemberName.java:1114)
    ... 43 common frames omitted

声明为抛出错误的 PersonModule 的第 23 行具有以下代码

 public PersonModule(PersonDAO dao){
        
        path("/api/user", () -> {
            get("", ctx -> {
                return dao.getPersons();
            });
            
            post("", ctx -> {
                Person person = ctx.body().to(Person.class);
                if (dao.getPerson(person.getEmail()) == null) {
                    dao.savePerson(person);
                    return ctx.send(StatusCode.CREATED);
                } else {
                    return ctx
                            .setResponseCode(StatusCode.UNPROCESSABLE_ENTITY)
                            .render(new ErrorMessage("That email already exists in the system"));
                }
            });
        });

return dao.getPersons()是第 23 行

获取人员的 JDBI 代码是

    @Override
    @SqlQuery("SELECT * FROM PERSON ORDER BY EMAIL")
    @RegisterBeanMapper(Person.class)
    public Collection<Person> getPersons();

和 Person.class 有以下代码(也包括普通的 getter 和 setter 方法)

 public Person(Integer personID, String email, String password, String firstName, String lastName, String phone, String mobile, String industry, String bio, String city, Boolean active, String findOut, String role, String notes) {
        this.personID = personID;
        this.email = email;
        this.password = password;
        this.firstName = firstName;
        this.lastName = lastName;
        this.phone = phone;
        this.mobile = mobile;
        this.industry = industry;
        this.bio = bio;
        this.city = city;
        this.active = active;
        this.findOut = findOut;
        this.role = role;
        this.notes = notes;
    }

我可以请帮助确定问题所在吗?

注意: GET 请求稍早进行了测试,似乎工作正常,即使数据库中有数据。 DAO 的单元测试也没有错误地通过。

在 SQL 查询中尝试实际的列名。 而不是这个:

SELECT * FROM PERSON ORDER BY EMAIL

尝试这个:

SELECT PERSONID, EMAIL, PASSWORD,... FROM PERSON ORDER BY EMAIL

您应该从错误输出中获得精髓。

它与构造函数 INIT 中的 lambda 代码相关,没有这样的方法 getPersons

有问题的代码应该有一个异常包装或添加到构造函数声明开始,据说至少对于获取请求代码,例如 throws ServletException 和 UnavailableException

GET /api/user 500 Server Error
java.lang.reflect.UndeclaredThrowableException: null
    at jdk.proxy2/jdk.proxy2.$Proxy16.getPersons(Unknown Source)
    at module.PersonModule.lambda$new$41b6884b$1(PersonModule.java:23)

    path("/api/user", () -> {
                get("", ctx -> {
                    return dao.getPersons();
                });
            
            

以下引用了一个奇怪的操作,即您使用 getPersons 方法将所有人员放到 Collection object 上,但除了将其返回我假定为“ ctx ”之外,您什么也不做,不幸的是,您实际上并没有说 object ctx 的类型是。

@Override
@SqlQuery("SELECT * FROM PERSON ORDER BY EMAIL")
@RegisterBeanMapper(Person.class)
public Collection<Person> getPersons();

不知何故,Person class 所需的所有构造函数参数都在帖子中发送,但在代码中没有生成 Person class ,我觉得奇怪的是,无论您是否给它一个无参数构造函数作为抽象,它都没有继续抛出错误class 有,但是想知道是不是把它当作抽象的 class 处理,比较正常的方法是做一个 DTO 数据传输 Object 模板和
DAO 数据访问 Object class 之间的实体,具有调用接口。 而且,getPersons 集合似乎没有任何用处,何必海量查询检索。

我发现了问题,

我的域 class 中的构造函数似乎是错误,我通过在当前的 Person.class 上方添加一个空构造函数来修复错误

public Person(){
        
    }

public Person(Integer personID, String email, String password, String firstName, String lastName, String phone, String mobile, String industry, String bio, Boolean active, String city,  String findOut, String role, String notes) {
        this.personID = personID;
        this.email = email;
        this.password = password;
        this.firstName = firstName;
        this.lastName = lastName;
        this.phone = phone;
        this.mobile = mobile;
        this.industry = industry;
        this.bio = bio;
        this.city = city;
        this.active = active;
        this.findOut = findOut;
        this.role = role;
    }

现在它工作正常。 如果有人解释为什么会这样,我很想知道:)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM