0

I have a Spring Boot Data REST project with the following classes

@Entity
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Product {
    @Id
    private String sku;

    @OneToMany(cascade = CascadeType.ALL,
            fetch = FetchType.EAGER,
            targetEntity = ProductMaterial.class)
    private List<ProductMaterial> materials;
}

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ProductMaterial {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @OneToOne
    private Material material;

    private float unitsPerProduct;
}


@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Material {
    @Id
    @GeneratedValue(strategy = GenerationType.UUID)
    private String id;

    private String description;
    private float costPerUnit;
    private int inStock;
}

And the following repositories:

@RepositoryRestResource(collectionResourceRel = "product", path = "products")
public interface ProductRepository extends PagingAndSortingRepository<Product, Long>, CrudRepository<Product, Long> {
}

@RepositoryRestResource(collectionResourceRel = "product-material", path = "product-materials", exported = false)
public interface ProductMaterialRepository extends PagingAndSortingRepository<ProductMaterial, String>, CrudRepository<ProductMaterial, String> {
}

@RepositoryRestResource(collectionResourceRel = "material", path = "materials")
public interface MaterialRepository extends PagingAndSortingRepository<Material, String>, CrudRepository<Material, String> {
}

I am also using org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.13 to generate the OpenAPI documentation. I have then generated a typescript-fetch client using the OpenAPI Generator CLI:

npx @openapitools/openapi-generator-cli generate -i http://localhost:8080/v3/api-docs -g typescript-fetch -o ./services/generated/api --additional-properties=supportsES6=false,modelPropertyNaming=original,withInterfaces=true,prependFormOrBodyParameters=true

On my client, I use the controller to post a product to my server like so:

new ProductEntityControllerApi().postCollectionResourceProductPost({
            productRequestBody: {
                ...product,
                materials: materials
            }
        })

The body that is sent with the request looks as follows:

{"sku":"PRD-001","name":"Test Produkt","materials":[{"id":-1,"material":{"id":"52a92362-3c7b-40e6-adfe-85a1007c121f","description":"Material 1","costPerUnit":1,"inStock":1},"unitsPerProduct":1},{"id":-1,"material":{"id":"8a0d57cc-d3bd-4653-b50f-d4a14d5183b3","description":"Material 4","costPerUnit":0.25,"inStock":4},"unitsPerProduct":1}],"sellPrice":"1.2"}

I have manually set the id to -1 while playing around, but it also fails with undefined and null.

After the post call is sent, I get the following exception:

org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `long` from String "52a92362-3c7b-40e6-adfe-85a1007c121f": not a valid `long` value

I don't quite understand the problem, to me it looks like the id of the material is resolved as the id of the product-material? How can I resolve this error?

1
  • I managed to get it working with a custom deserializer, but I feel like there is probably some other, more spring-like solution. Commented Oct 28 at 9:23

1 Answer 1

0

Solution is very simple. You just need to follow step by step class attributes with it's required types. As per your request, you are facing an issue regarding JSON Parse Error. You just need to use long value instead String value. Because, in your ProductMaterial class you are using long type and here you are using String value. So, this is the main issue. Just use necessary data type value with id and try again with same request, you will not face same issue again.

Your request :

Your JSON :

{
  "sku": "PRD-001",
  "name": "Test Produkt",
  "materials": [
    {
      "id": -1,
      "material": {
        "id": "52a92362-3c7b-40e6-adfe-85a1007c121f",
        "description": "Material 1",
        "costPerUnit": 1,
        "inStock": 1
      },
      "unitsPerProduct": 1
    },
    {
      "id": -1,
      "material": {
        "id": "8a0d57cc-d3bd-4653-b50f-d4a14d5183b3",
        "description": "Material 4",
        "costPerUnit": 0.25,
        "inStock": 4
      },
      "unitsPerProduct": 1
    }
  ],
  "sellPrice": "1.2"
}

New Sample JSON (Try and Check) :

{
  "sku": "PRD-001",
  "name": "Test Produkt",
  "materials": [
    {
      "id": -1,
      "material": {
        "id": 1,
        "description": "Material 1",
        "costPerUnit": 1,
        "inStock": 1
      },
      "unitsPerProduct": 1
    },
    {
      "id": -1,
      "material": {
        "id": 2,
        "description": "Material 4",
        "costPerUnit": 0.25,
        "inStock": 4
      },
      "unitsPerProduct": 1
    }
  ],
  "sellPrice": "1.2"
}
Sign up to request clarification or add additional context in comments.

2 Comments

I had the same problem when using the same datatype as well. They were both strings before I changed the product-material id to long to try and get around that error this way. In that case, it tried to find the product-material using the material id which led to sql exceptions
If you getting SQL Exceptions then you must check Entity class which you are using for this task. After that check mapping from both the side like code side which will be your entity class attribute and database side which will be using proper data-types as well.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.