NumberFormatException: For input string: "" in Swagger (Solved)

In my previous article about Documenting Spring Boot REST API with Swagger, I mentioned about following "error" while running the program and/or accessing api-docs (or swagger-ui):

2020-05-02 21:25:56.584 WARN 15140 --- [nio-8080-exec-1] i.s.m.p.AbstractSerializableParameter : Illegal DefaultValue null for parameter type integer java.lang.NumberFormatException: For input string: "" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) ~[na:1.8.0_181] at java.lang.Long.parseLong(Long.java:601) ~[na:1.8.0_181] at java.lang.Long.valueOf(Long.java:803) ~[na:1.8.0_181] at io.swagger.models.parameters.AbstractSerializableParameter.getExample(AbstractSerializableParameter.java:412) ~[swagger-models-1.5.20.jar:1.5.20] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_181] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_181] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_181] at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_181] at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:688) [jackson-databind-2.10.2.jar:2.10.2] at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:722) [jackson-databind-2.10.2.jar:2.10.2] at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:166) [jackson-databind-2.10.2.jar:2.10.2]

To be precise, this is not an error, its just a warning log message. And I already give one workaround in my article. But if you not happy with just a workaround, and want a solution, then you must fix your code.

First, you need to check any @ApiModelProperty annotation. You must set an example value on any numeric type property and annotated with @ApiModelProperty, like below:

@ApiModelProperty(notes = "Unique identifier of the Contact.", example = "1", required = true, position = 0) @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Long id;

But for my sample program, that's not enough. You also need to set example value for each parameter that uses the @ApiParam annotation and has a field type of numeric type. You need to set it, as following:

public ResponseEntity<Contact> findContactById( @ApiParam(name = "contactId", value = "Id of the contact to be obtained. Cannot be empty.", example = "1", required = true) @PathVariable long contactId) { ... return ... }

So my ContactController is changed from:

@Api(description = "Endpoints for Creating, Retrieving, Updating and Deleting of Contacts.",
        tags = {"contact"})
@RestController
@RequestMapping("/api")
public class ContactController {
    
    ...
    
    @ApiOperation(value = "Find Contacts by name", notes = "Name search by %name% format", tags = { "contact" })
    @ApiResponses(value = {
        @ApiResponse(code = 200, message = "successful operation", response=List.class )  })	    
    @GetMapping(value = "/contacts")
    public ResponseEntity<List<Contact>> findAll(
            @ApiParam("Page number, default is 1") @RequestParam(value="page", defaultValue="1") int pageNumber,
            @ApiParam("Name of the contact for search.") @RequestParam(required=false) String name) {
        ...
	return ...
    }

    @ApiOperation(value = "Find contact by ID", notes = "Returns a single contact", tags = { "contact" })
    @ApiResponses(value = {
        @ApiResponse(code = 200, message = "successful operation", response=Contact.class),
        @ApiResponse(code = 404, message = "Contact not found") })
    @GetMapping(value = "/contacts/{contactId}", produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<Contact> findContactById(
            @ApiParam("Id of the contact to be obtained. Cannot be empty.")
            @PathVariable long contactId) {
        ...
	return ...
    }
    
    @ApiOperation(value = "Add a new contact", tags = { "contact" })
    @ApiResponses(value = { 
        @ApiResponse(code = 201, message = "Contact created"), 
        @ApiResponse(code = 400, message = "Invalid input"), 
        @ApiResponse(code = 409, message = "Contact already exists") })	    
    @PostMapping(value = "/contacts")
    public ResponseEntity<Contact> addContact(
            @ApiParam("Contact to add. Cannot null or empty.")
            @Valid @RequestBody Contact contact) 
            throws URISyntaxException {
        ...
	return ...
    }
    
    @ApiOperation(value = "Update an existing contact", tags = { "contact" })
    @ApiResponses(value = {
        @ApiResponse(code = 200, message = "successful operation"),
        @ApiResponse(code = 400, message = "Invalid ID supplied"),
        @ApiResponse(code = 404, message = "Contact not found"),
        @ApiResponse(code = 405, message = "Validation exception") })
    @PutMapping(value = "/contacts/{contactId}")
    public ResponseEntity<Contact> updateContact(
            @ApiParam("Id of the contact to be update. Cannot be empty.")
            @PathVariable long contactId,
            @ApiParam("Contact to update. Cannot null or empty.")
            @Valid @RequestBody Contact contact) {
        ...
	return ...
    }
    
    @ApiOperation(value = "Update an existing contact's address", tags = { "contact" })
    @ApiResponses(value = {
        @ApiResponse(code = 200, message = "successful operation"),
        @ApiResponse(code = 404, message = "Contact not found") })
    @PatchMapping("/contacts/{contactId}")
    public ResponseEntity<Void> updateAddress(
            @ApiParam("Id of the contact to be update. Cannot be empty.")
            @PathVariable long contactId,
            @ApiParam("Contact's address to update.")
            @RequestBody Address address) {
        ...
	return ...
    }
    
    @ApiOperation(value = "Deletes a contact", tags = { "contact" })
    @ApiResponses(value = { 
        @ApiResponse(code = 200, message = "successful operation"),
        @ApiResponse(code = 404, message = "Contact not found") })
    @DeleteMapping(path="/contacts/{contactId}")
    public ResponseEntity<Void> deleteContactById(
            @ApiParam("Id of the contact to be delete. Cannot be empty.")
            @PathVariable long contactId) {
        ...
	return ...
    }
}
                    

To:

@Api(description = "Endpoints for Creating, Retrieving, Updating and Deleting of Contacts.",
        tags = {"contact"})
@RestController
@RequestMapping("/api")
public class ContactController {

    ...

    @ApiOperation(value = "Find Contacts by name", notes = "Name search by %name% format", tags = {"contact"})
    @ApiResponses(value = {
        @ApiResponse(code = 200, message = "successful operation", response = List.class)})
    @GetMapping(value = "/contacts")
    public ResponseEntity<List<Contact>> findAll(
            @ApiParam(name = "contactId",
                    value = "Page number, default is 1",
                    example = "1",
                    required = false) @RequestParam(value = "page", defaultValue = "1") int pageNumber,
            @ApiParam("Name of the contact for search.") @RequestParam(required = false) String name) {
        ...
	return ...
    }

    @ApiOperation(value = "Find contact by ID", notes = "Returns a single contact", tags = {"contact"})
    @ApiResponses(value = {
        @ApiResponse(code = 200, message = "successful operation", response = Contact.class),
        @ApiResponse(code = 404, message = "Contact not found")})
    @GetMapping(value = "/contacts/{contactId}", produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<Contact> findContactById(
            @ApiParam(name = "contactId",
                    value = "Id of the contact to be obtained. Cannot be empty.",
                    example = "1",
                    required = true)
            @PathVariable long contactId) {
        ...
	return ...
    }

    @ApiOperation(value = "Add a new contact", tags = {"contact"})
    @ApiResponses(value = {
        @ApiResponse(code = 201, message = "Contact created"),
        @ApiResponse(code = 400, message = "Invalid input"),
        @ApiResponse(code = 409, message = "Contact already exists")})
    @PostMapping(value = "/contacts")
    public ResponseEntity<Contact> addContact(
            @ApiParam("Contact to add. Cannot null or empty.")
            @Valid @RequestBody Contact contact)
            throws URISyntaxException {
        ...
	return ...
    }

    @ApiOperation(value = "Update an existing contact", tags = {"contact"})
    @ApiResponses(value = {
        @ApiResponse(code = 200, message = "successful operation"),
        @ApiResponse(code = 400, message = "Invalid ID supplied"),
        @ApiResponse(code = 404, message = "Contact not found"),
        @ApiResponse(code = 405, message = "Validation exception")})
    @PutMapping(value = "/contacts/{contactId}")
    public ResponseEntity<Contact> updateContact(
            @ApiParam(name = "contactId",
                    value = "Id of the contact to be update. Cannot be empty.",
                    example = "1",
                    required = true)
            @PathVariable long contactId,
            @ApiParam("Contact to update. Cannot null or empty.")
            @Valid @RequestBody Contact contact) {
        ...
	return ...
    }

    @ApiOperation(value = "Update an existing contact's address", tags = {"contact"})
    @ApiResponses(value = {
        @ApiResponse(code = 200, message = "successful operation"),
        @ApiResponse(code = 404, message = "Contact not found")})
    @PatchMapping("/contacts/{contactId}")
    public ResponseEntity<Void> updateAddress(
            @ApiParam(name = "contactId",
                    value = "Id of the contact to be update. Cannot be empty.",
                    example = "1",
                    required = true)
            @PathVariable long contactId,
            @ApiParam("Contact's address to update.")
            @RequestBody Address address) {
        ...
	return ...
    }

    @ApiOperation(value = "Deletes a contact", tags = {"contact"})
    @ApiResponses(value = {
        @ApiResponse(code = 200, message = "successful operation"),
        @ApiResponse(code = 404, message = "Contact not found")})
    @DeleteMapping(path = "/contacts/{contactId}")
    public ResponseEntity<Void> deleteContactById(
            @ApiParam(name = "contactId",
                    value = "Id of the contact to be delete. Cannot be empty.",
                    example = "1",
                    required = true)
            @PathVariable long contactId) {
        ...
	return ...
    }
}
                    

Check all those @ApiParam with example. Now, that warning gone...