【问题标题】:mvn spring-boot:run "No primary or single public constructor found...TemplateLineItemInput" but only from commandline?mvn spring-boot:run "No primary or single public constructor found...TemplateLineItemInput" 但只能从命令行运行?
【发布时间】:2021-11-26 01:17:42
【问题描述】:

我有一个中级的 Spring Boot + Lombok 项目,它的工作方式类似于 IDE 中的冠军,但是当我从命令行通过mvn spring-boot:run 运行它时会出现奇怪的错误。它是一个相当新的版本 Spring Boot...

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

Lombok 不起眼,来自 Spring Initializr (https://start.spring.io/)。

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

它抱怨的JavaBean同样无聊......

import lombok.Builder;
import lombok.Data;

import java.math.BigDecimal;

@Data
@Builder(toBuilder = true)
public class TemplateLineItemInput {
  private final String partMasterId;
  private final String partMasterIdPath;
  private final String actionType;
  private final BigDecimal actionQuantity;
}

这个 Boot 项目的 API 是 GraphQL,但是当我从 mvn spring-boot:run 调用中执行以下突变时,它总是以错误的形式返回(控制台上没有任何内容......框架以某种方式将其踢出)。

Request...

mutation createTemplateLineItem($tbomId: ID!) {
  createTemplateLineItem(
    tbomId: $tbomId
    input: {
      partMasterId: "2"
      partMasterIdPath: "808863036.1"
      actionType: "ADD"
      actionQuantity: "2"
    }) {
    ...TBomFrag
  }
}
...
{
  "partMasterId": "5025489768",
  "tbomId": "a4688d22-9d99-41a2-9777-6acc75b2aab9",
  "lineItemId": "9e460199-34fb-432c-b971-8cd8321d3283"
}

Response...
{
  "errors": [
    {
      "message": "No primary or single public constructor found for class aero.blue.ems.boa.domain.TemplateLineItemInput - and no default constructor found either",
      "locations": [
        {
          "line": 20,
          "column": 3
        }
      ],
      "path": [
        "createTemplateLineItem"
      ],
      "extensions": {
        "classification": "INTERNAL_ERROR"
      }
    }
  ],
  "data": {
    "createTemplateLineItem": null
  }
}

我的spring-boot-maven-plugin 配置为...

            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.5.4</version>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
                <executions>
                    <execution>
                        <id>repackage</id>
                        <configuration>
                            <classifier>exec</classifier>
                        </configuration>
                    </execution>
                    <execution>
                        <goals>
                            <goal>build-info</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

...同样来自 Spring Initializr

当我直接从 IDE 运行应用程序时,没有问题。突变工作正常。

pom.xml 中的 spring-boot:run 配置是否缺少某些内容?我是否必须将插件引入注释处理?这真是令人困惑。

【问题讨论】:

  • 哦....我的...一个线索。 stackoverflow.com/questions/34241718/… 我的 @Builder 使用可能会影响 Lombok 正在构建的构造函数,因此杰克逊无法再处理它。 “Delombok”在这里很有用。我确实确实没有公共构造函数。为什么它在 IDE 中工作?也许没关系....我知道杰克逊需要公开的东西

标签: spring-boot maven lombok graphql-java


【解决方案1】:

最终这归结为我的 bean 的 Lombok 配置错误。解决方法是将@AllArgsConstructor 添加到 bean 定义中

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;

import java.math.BigDecimal;

@Data
@Builder(toBuilder = true)
@AllArgsConstructor
public class TemplateLineItemInput {
  private final String partMasterId;
  private final String partMasterIdPath;
  private final String actionType;
  private final BigDecimal actionQuantity;
}

我们如何解决这个问题是“Delombok” Bean 并查看生成的代码。该观察结果与错误消息相符;没有公共构造函数。

  ...
  TemplateLineItemInput(String partMasterId, String partMasterIdPath, String actionType, BigDecimal actionQuantity) {
    this.partMasterId = partMasterId;
    this.partMasterIdPath = partMasterIdPath;
    this.actionType = actionType;
    this.actionQuantity = actionQuantity;
  }

不知何故(我仍然不完全明白为什么),@Builder(toBuilder=true) 注释让 Lombok 产生了一个包私有构造函数。杰克逊需要一些公开的东西。

添加 @AllArgsConstructor 注释使构造函数公开,一切正常。

  public TemplateLineItemInput(String partMasterId, String partMasterIdPath, String actionType, BigDecimal actionQuantity) {
    this.partMasterId = partMasterId;
    this.partMasterIdPath = partMasterIdPath;
    this.actionType = actionType;
    this.actionQuantity = actionQuantity;
  }

Delombok 是关键。

【讨论】:

    【解决方案2】:

    在 pom.xml 项目的部分插件上检查以下配置,如下所示:

    <project>
        <modelVersion>4.0.0</modelVersion>
        <artifactId>getting-started</artifactId>
        <!-- ... -->
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    </project>
    

    有关更多信息,请查看此链接:https://docs.spring.io/spring-boot/docs/2.5.4/maven-plugin/reference/htmlsingle/

    【讨论】:

    • 有趣。我对该插件的配置不包括lombok。我把它拿出来了,但问题仍然存在。我将我当前的配置添加到问题中。
    • @BobKuhar 首先,您是否有同样的问题,当您在 maven 包阶段之后对 jar 生成的包执行 java -jar 命令时,位于目标文件夹:target/foo-0.0 .1.jar?其次,根据 lombok 的文档,:projectlombok.org/api/lombok/Builder.html 在 TemplateLineItemInput 的类级别使用此注释(@Builder),在 lombok 处理中生成一个私有构造函数。
    • 我确实得到了与java -jar target/bom-authoring-service-exec.jar 相同的坏结果。我需要那个@Builder,并且我希望@Data 的不变量只是在生成的bean 中“出现”。我仍然感到很奇怪,这在 IDE 中有效,而在其他任何地方都无效。我不知道如何自省生成的 JAR 以查看 Java 在生成的 Bean 上的实际外观。
    • 我的 lombok 依赖和 spring-boot-maven-plugin 配置都来自 Spring Initializr。还是陌生的。谁错了?我应该开始回滚 Spring Boot 版本吗?
    猜你喜欢
    • 2017-04-26
    • 2020-02-27
    • 2018-10-12
    • 2014-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多