<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Spring Boot &#8211; CodePills.com</title>
	<atom:link href="https://codepills.com/tag/spring-boot/feed/" rel="self" type="application/rss+xml" />
	<link>https://codepills.com</link>
	<description>Helping you make a better code</description>
	<lastBuildDate>Sun, 18 Feb 2024 09:01:54 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	
	<item>
		<title>How to make multipart requests with file and object through autogenerated code defined in OpenAPI</title>
		<link>https://codepills.com/how-to-make-multipart-requests-with-file-and-object-through-autogenerated-code-defined-in-openapi/</link>
					<comments>https://codepills.com/how-to-make-multipart-requests-with-file-and-object-through-autogenerated-code-defined-in-openapi/#respond</comments>
		
		<dc:creator><![CDATA[Andrej Buday]]></dc:creator>
		<pubDate>Sat, 03 Feb 2024 18:08:37 +0000</pubDate>
				<category><![CDATA[Solutions]]></category>
		<category><![CDATA[Converter]]></category>
		<category><![CDATA[Deserialization]]></category>
		<category><![CDATA[Endpoint Creation]]></category>
		<category><![CDATA[File Upload]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Multipart Form Data]]></category>
		<category><![CDATA[MultipartFile]]></category>
		<category><![CDATA[Object Validation]]></category>
		<category><![CDATA[ObjectMapper]]></category>
		<category><![CDATA[OpenAPI]]></category>
		<category><![CDATA[Postman]]></category>
		<category><![CDATA[Spring Boot]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[Validator]]></category>
		<guid isPermaLink="false">https://codepills.com/?p=1364</guid>

					<description><![CDATA[This article explains how to create a Spring Boot endpoint using OpenAPI to receive objects and, optionally, files through multipart form data, focusing on deserialization and validation of incoming objects. <a href="https://codepills.com/how-to-make-multipart-requests-with-file-and-object-through-autogenerated-code-defined-in-openapi/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<p>This article explains creating a Spring Boot endpoint using OpenAPI to receive objects and, optionally, files through multipart form data, focusing on deserialization and validation of incoming objects.</p>
<p><span id="more-1364"></span></p>
<h2>Introduction</h2>
<p>In this article we will continue and spin from the <a href="https://codepills.com/how-to-make-multipart-requests-with-files-through-autogenerated-code-defined-in-openapi/" title="How to make multipart requests with files through autogenerated code defined in OpenAPI" target="_blank" rel="nofollow noopener">previous article</a> about generating OpenAPI with Spring Boot for multipart endpoint and uploading files through it. We strongly recommend reading the last article if you want to import more than one file. But in this article, we will focus only on the optional import of a single file.</p>
<p>But instead of multiple files, we will try to upload only one file and one serialized object, for example, the information about the new user.</p>
<p>We will also show how to handle the deserialization of the incoming object from the string at the Spring Boot backend and how to control proper deconstruction if some fields are optional or not mandatory.</p>
<h2>OpenAPI User import definition YAML</h2>
<p>So we start where we end the last time. Let&#8217;s generate the Spring Boot endpoint through the OpenAPI schema, which will be able to receive objects and, optionally, a file through multipart form data.</p>
<pre><code class="language-yaml">openapi: 3.0.2
info:
  title: User management module
  description: User management
  version: '0.1'
  contact:
  email: optional@email.com
servers:
  - url: https://localhost:8080/api/user-management

paths:
  /users/import:
    post:
      summary: Create new Users with optional attachment
      tags:
        - users
      operationId: createUserWithOptionalFile
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                createUser:
                  description: Wrapper containing information for new user creation
                  type: object
                  properties:
                    username:
                      description: Users username
                      type: string
                    age:
                      description: Users password
                      type: number
                    creationTimestamp:
                      description: Time when the user will be defined as created in the system
                      type: string
                      format: date-time
                      example: "2024-02-29T12:30:00.000Z"
                    email:
                      description: Email of the user
                      type: string
                    addressId:
                      description: ID of the users address
                      type: string
                    accessRights:
                      description: List of access rights for the user
                      type: array
                      items:
                        type: object
                        properties:
                          accessRightId:
                            description: ID of the access right
                            type: string
                          note:
                            description: Note for the access right
                            type: string
                  required:
                    - username
                    - email
                    - accessRights
                optionalFile:
                  description: Optional file attachment
                  type: string
                  format: binary
              required:
              - createUser
      responses:
        '200':
          description: Successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateUserResponse'
        '400':
          description: Bad Request</code></pre>
<p>As you can see, we have defined the endpoint /users/import, which will be able to receive the object createUser and optionally also a single file. The createUser object is defined in the schema and is required, while the file is optional. CreateUser object also has various definitions of fields, although unimportant and displayed only for current examples.</p>
<p>You can refer to the object schema to make the YAML file more readable and concise. The object&#8217;s schema can be defined in self-standing section dedicated to components.</p>
<pre><code class="language-yaml">openapi: 3.0.2
info:
  title: User management module
  description: User management
  version: '0.1'
  contact:
  email: optional@email.com
servers:
  - url: https://localhost:8080/api/user-management

paths:
  /users/import:
    post:
      summary: Create new Users with optional attachment
      tags:
        - users
      operationId: createUserWithOptionalFile
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                createUser:
                  $ref: '#/components/schemas/CreateUser'
                optionalFile:
                  description: Optional file attachment
                  type: string
                  format: binary
              required:
              - createUser
      responses:
        '200':
          description: Successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateUserResponse'
        '400':
          description: Bad Request

components:
  schemas:
    CreateUser:
      description: Wrapper containing information for new user creation
      type: object
      properties:
        username:
          description: Users username
          type: string
        age:
          description: Users password
          type: number
        creationTimestamp:
          description: Time when the user will be defined as created in the system
          type: string
          format: date-time
          example: "2024-02-29T12:30:00.000Z"
        email:
          description: Email of the user
          type: string
        addressId:
          description: ID of the users address
          type: string
        accessRights:
          description: List of access rights for the user
          type: array
          items:
            type: object
            properties:
              accessRightId:
                description: ID of the access right
                type: string
              note:
                description: Note for the access right
                type: string
      required:
        - username
        - email
        - accessRights</code></pre>
<h2>Enforcing and casting mandatory properties of multipart request</h2>
<p>Multipart file can accept only the <i>String</i>s or <i>File</i>s (better visible in <a href="#testing_with_postman">testing with Postman</a> section). So any string input &#8211; Java&#8217;s serialized object, or JSON, is at the end nothing more than just a string of bytes.</p>
<p>The problem will arise during the deserialization of autogenerated code. It does not matter if you declare the object cast as required. With proper mapping, the input will be taken as a String and not as the type you want to use from the method signature.</p>
<p>Mapper and validator factory beans can solve the issue and handle the input.</p>
<p>First, register one new bean for object Validation. Optionally, you can register the ObjectMapper with JavaTimeModule to handle the date-time format, as we will use the date-time string in ISO format (&#8220;YYYY-MM-DDTHH:MM:SS.mmmZ&#8221;). The Validator is created through LocalValidatorFactoryBean.</p>
<pre><code class="language-java">import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

import jakarta.validation.Validator;
import lombok.val;

@Configuration
public class AppConfig {

  //@Bean
  //public ObjectMapper objectMapper() {
  //  val objectMapper = new ObjectMapper();
  //  objectMapper.registerModule(new JavaTimeModule());
  //  return objectMapper;
  //}

  @Bean
  public Validator validator() {
    return new LocalValidatorFactoryBean();
  }

}</code></pre>
<p>The code was written for Java 21 dependencies with Lombok.</p>
<p>To enforce the proper conversion, you must create a new Spring component to convert the incoming string to the object. The component will be able to handle the deserialization and validation of the object.</p>
<pre><code class="language-java">import java.util.Set;

import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;

import com.fasterxml.jackson.databind.ObjectMapper;

import jakarta.validation.ConstraintViolation;
import jakarta.validation.ConstraintViolationException;
import jakarta.validation.Validator;
import lombok.val;

@Component
public class StringToCreateUserDtoConverter implements Converter&lt;String, CreateUserDto> {

  private final Validator validator;
  private final ObjectMapper objectMapper;

  public StringToCreateUserDtoConverter(final Validator validator, final ObjectMapper objectMapper) {
    this.validator = validator;
    this.objectMapper = objectMapper;
  }

  @Override
  public CreateUserDto convert(final String source) {
    CreateUserDto createUserDto;
    try {
        createUserDto = objectMapper.readValue(source, CreateUserDto.class);
    } catch (JsonProcessingException e) {
        throw new CreateUserDeserializationException("Input mapping and processing error: " + e.getMessage());
    }
    val violations = validator.validate(createUserDto);
    if (!violations.isEmpty()) {
        throw new ConstraintViolationException(violations);
    }
    return createUserDto;
  }

}</code></pre>
<p>Just for the record, I will also add here the custom exception you can throw and catch in the custom exception handler:</p>
<pre><code class="language-java">import java.io.Serial;

import lombok.Getter;

@Getter
public class CreateUserDeserializationException extends RuntimeException {

  @Serial
  private static final long serialVersionUID = 1659771269447893294L;

  public CreateUserDeserializationException(String msg) {
    super(msg);
  }

}</code></pre>
<h2>Unit tests</h2>
<p>I recommend writing the unit tests for the converter. It is a good practice to test the conversion and validation of the object. As we rely heavily upon Spring magic, a lot can unintentionally influence the component&#8217;s behaviour without us discovering it.</p>
<p>The code below is just an example of the unit tests with the usage of <i>SpringBootTest</i> and <i>LocalTestcontainers</i> which ties to get close to real-world use scenarios. We highly recommend to accommodate tests to your environment and needs.</p>
<pre><code class="language-java">
import org.testcontainers.containers.PostgreSQLContainer;

public class LocalTestcontainers {

    public static void startPostgres(){
        PostgreSQLContainer<?> postgre = new PostgreSQLContainer<>("postgres:16.0")
            .withDatabaseName("INSERT_DATABASE_NAME")
            .withUsername("INSERT_DATABASE_USERNAME")
            .withPassword("INSERT_DATABASE_PASSWORD");
        postgre.start();

        System.setProperty("spring.datasource.url", postgre.getJdbcUrl());
        System.setProperty("spring.datasource.username", postgre.getUsername());
        System.setProperty("spring.datasource.password", postgre.getPassword());
    }

}</code></pre>
<pre><code class="language-java">import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

import java.math.BigDecimal;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.util.UUID;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.testcontainers.junit.jupiter.Testcontainers;

import com.codepills.usermanagementmodule.api.exception.CreateUserDeserializationException;
import com.codepills.usermanagementmodule.utils.LocalTestcontainers;

import jakarta.validation.ConstraintViolationException;
import lombok.val;

@SpringBootTest
@Testcontainers
class StringToCreateUserDtoConverterTest {

    static {
        LocalTestcontainers.startPostgres();
    }

    @Autowired
    private StringToCreateUserDtoConverter stringToCreateUserDtoConverter;

    @Test
    void testConvertValidInputString() {
        // Arrange
        val username = "JohnDoe";
        val age = 25;
        val formatter = DateTimeFormatter.ISO_INSTANT;
        val now4CreationTime = Instant.now();
        val email = "john.doe@noemail.com";
        val addressId = UUID.randomUUID();
        val accessRightId1 = UUID.randomUUID();
        val accessRightId2 = UUID.randomUUID();

        val stringBuilder = new StringBuilder();
        stringBuilder.append("{");
        stringBuilder.append("\"username\" : \"").append(username).append("\",");
        stringBuilder.append("\"age\" : ").append(age).append(",");
        stringBuilder.append("\"creationTimestamp\" : \"").append(formatter.format(now4CreationTime)).append("\",");
        stringBuilder.append("\"email\" : \"").append(email).append("\",");
        stringBuilder.append("\"addressId\" : \"").append(addressId).append("\",");
        stringBuilder.append("\"accessRights\" : [");
        stringBuilder.append("{");
        stringBuilder.append("\"accessRightId\" : \"").append(accessRightId1).append("\",");
        stringBuilder.append("}, {");
        stringBuilder.append("\"accessRightId\" : \"").append(accessRightId2).append("\"");
        stringBuilder.append("}]}");
        val validInput = stringBuilder.toString();

        // Act
        val createUserDto = stringToCreatUserDtoConverter.convert(validInput);

        // Assert
        assertNotNull(createUserDto);
        assertEquals(username, createUserDto.getUsername());
        assertEquals(age, createUserDto.getAge());
        assertEquals(now4CreationTime, createUserDto.getCreationTimestamp());
        assertEquals(email, createUserDto.getEmail());
        assertEquals(addressId.toString(), createUserDto.getAddressId());
        assertEquals(2, createUserDto.getAccessRights().size());
        assertEquals(accessRightId1.toString(), createUserDto.getAccessRights().get(0).getAccessRightId());
        assertEquals(accessRightId2.toString(), createUserDto.getAccessRights().get(1).getAccessRightId());
    }

    @Test
    void testConvertInvalidInputString() {
        // Arrange
        val invalidInput = "invalid input string";
        // Act & Assert
        try {
            stringToCreateUserDtoConverter.convert(invalidInput);
        } catch (CreateUserDeserializationException ex) {
            assertEquals("Input mapping and processing error: Unrecognized token 'invalid': was expecting (JSON String, Number, Array, "
                             + "Object or token 'null', 'true' or 'false')\n at [Source: (String)\"invalid input string\"; line: 1, "
                             + "column: 8]", ex.getMessage());
        }
    }

    @Test
    void testConvertInputWithValidationErrors() {
        // Arrange
        val username = "JohnDoe";
        val age = 25;
        val formatter = DateTimeFormatter.ISO_INSTANT;
        val now4CreationTime = Instant.now();
        val email = "john.doe@noemail.com";
        val addressId = UUID.randomUUID();
        val accessRightId1 = UUID.randomUUID();
        val accessRightId2 = UUID.randomUUID();

        val stringBuilder = new StringBuilder();
        stringBuilder.append("{");
        stringBuilder.append("\"username\" : \"").append(username).append("\",");
        stringBuilder.append("\"age\" : ").append(age).append(",");
        stringBuilder.append("\"creationTimestamp\" : \"").append(formatter.format(now4CreationTime)).append("\",");
        stringBuilder.append("\"email\" : \"").append(email).append("\",");
        // Missing addressId
        stringBuilder.append("\"addressId\" : null,");
        stringBuilder.append("\"accessRights\" : [");
        stringBuilder.append("{");
        stringBuilder.append("\"accessRightId\" : \"").append(accessRightId1).append("\",");
        stringBuilder.append("}, {");
        stringBuilder.append("\"accessRightId\" : \"").append(accessRightId2).append("\"");
        stringBuilder.append("}]}");
        val validInput = stringBuilder.toString();

        // Act & Assert
        try {
            stringToCreateUserDtoConverter.convert(inputWithValidationErrors);
        } catch (ConstraintViolationException ex) {
            assertEquals(1, ex.getConstraintViolations().size());
        }
    }

}</code></pre>
<h2>User Management Controller</h2>
<p>Now, all we need to do is create a controller to implement the OpenAPI schema.</p>
<p>Here is an example of the controller:</p>
<pre><code class="language-java">@Logger
@RestController
@RequiredArgsConstructor
public class UserManagementController implements UserManagementApi {

  @Override
  public ResponseEntity&lt;Void&gt&gt; createUserWithOptionalFile(
        @RequestPart(name = "createUser") final CreateUserDto createUserDto,
        @RequestPart(name = "optionalFile", required = false) MultipartFile optionalFile
     ) {
    if (optionalFile == null || optionalFile.isEmpty()) {
        log.info("No optionalFile uploaded.");
    } else {
        log.info("PDF optionalFile {} uploaded but not saved.", optionalFile.getOriginalFilename());
    }

    // You can work with createUserDto here

    return ResponseEntity.ok().build();
  }

}</code></pre>
<p>I will leave the implementation of <em>createUserWithOptionalFile()</em> method up to you as it is not the main focus of this article.</p>
<p>Again, notice the <i>optionalFile</i> and <i>createUser</i> keywords in the method arguments. It is the same as the keyword as defined in the OpenAPI schema.</p>
<h2 id="testing_with_postman">Testing with Postman</h2>
<p>Nothing blocks our development anymore, and we can start testing the endpoint with Postman. The endpoint will be able to receive the serialized object in the form of string and also the file. However, attaching the file to the request is, of course, optional.</p>
<p>As it might need to be stressed more, the most important thing is using the exact keywords defined in the OpenAPI schema. In our case, for importing object, it will be <i>createUser</i> and for optional file, it will be <i>optionalFile</i>.</p>
<p>Let&#8217;s run the SpringBoot app at localhost.</p>
<p>Backend should be running at localhost. And if added the necessary logic for file processing into the controller, we should be able to upload serialized objects in JSON format and optional file through the <em>/users/import</em> endpoint.</p>
<p>When using Postman, you also need to define the type of multipart key. It is either the <em>String</em> or <em>File</em>. For files, use <em>File</em>, and for the object, use <em>String</em>. Do not forget that in the <a href="https://codepills.com/how-to-make-multipart-requests-with-files-through-autogenerated-code-defined-in-openapi/" title="How to make multipart requests with files through autogenerated code defined in OpenAPI" target="_blank" rel="nofollow noopener">previous article</a> we discuss the implementation of sending multiple files through multipart request.</p>
<p>All you need to do is to define your endpoint <code>POST</code> request in Postman. Select <code>POST</code> request, add the URL, and in the body tab, select form-data and add the keywords <em>createUser</em> set as <em>String</em> and <em>optionalFile</em> as <em>File</em> .</p>
<p><img fetchpriority="high" decoding="async" src="https://codepills.com/wp-content/uploads/2024/02/postman_multipart_request_with_multiple_objects_and_files.png" alt="Postman multipart request with multiple objects and files" width="665" height="316" class="size-full wp-image-1373" srcset="https://codepills.com/wp-content/uploads/2024/02/postman_multipart_request_with_multiple_objects_and_files.png 665w, https://codepills.com/wp-content/uploads/2024/02/postman_multipart_request_with_multiple_objects_and_files-300x143.png 300w" sizes="(max-width: 665px) 100vw, 665px" /></p>
<p>The most important part is to really define serialized object as <em>String</em> and not <em>File</em>.</p>
<p>Here is an example of <em>createUser</em> as <em>String</em>:</p>
<pre><code class="language-text">{
	"username" : "johndoe",
	"age" : "25",
	"creationTimestamp" : "2024-02-29T12:30:00.000Z",
	"email" : "john.doe@noemail.com",
	"addressId" : "f8935f28-8d7b-40a4-96d7-a3288976617e",
	"accessRights" : [
		{
      "accessRightId" : "712d5a0a-11b5-4a44-9e92-6e67d16be2aa"
    }
	]
}</code></pre>
<h2>Conclusion</h2>
<p>This article has shown how to create a Spring Boot endpoint to receive objects and, optionally, file through multipart form data. We have also demonstrated how to handle the deserialization of the incoming object from the string at the Spring Boot backend and how to control proper deconstruction if some fields are optional or not mandatory.</p>
<p>Is it applicable to auto-generating infrastructure code through OpenAPI with Spring Boot for multipart endpoint and uploading files? Let us know in the comments below. Do you have your trick or see another way <u>how to enforce and deserialize multipart object</u>? Let us know in the comments below the article. We would like to hear your ideas and stories.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://codepills.com/how-to-make-multipart-requests-with-file-and-object-through-autogenerated-code-defined-in-openapi/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to make multipart requests with files through autogenerated code defined in OpenAPI</title>
		<link>https://codepills.com/how-to-make-multipart-requests-with-files-through-autogenerated-code-defined-in-openapi/</link>
					<comments>https://codepills.com/how-to-make-multipart-requests-with-files-through-autogenerated-code-defined-in-openapi/#respond</comments>
		
		<dc:creator><![CDATA[Andrej Buday]]></dc:creator>
		<pubDate>Thu, 01 Feb 2024 15:55:58 +0000</pubDate>
				<category><![CDATA[Solutions]]></category>
		<category><![CDATA[Auto-generated Code]]></category>
		<category><![CDATA[Maven Plugin]]></category>
		<category><![CDATA[Multipart File Uploads]]></category>
		<category><![CDATA[OpenAPI Schema]]></category>
		<category><![CDATA[Postman Testing]]></category>
		<category><![CDATA[REST Endpoint]]></category>
		<category><![CDATA[Spring Boot]]></category>
		<guid isPermaLink="false">https://codepills.com/?p=1360</guid>

					<description><![CDATA[This article provides a clear tutorial on generating infrastructure code defined in OpenAPI schema for your custom Spring Boot application and handling multipart file uploads through an autogenerated REST endpoint. <a href="https://codepills.com/how-to-make-multipart-requests-with-files-through-autogenerated-code-defined-in-openapi/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<p>This article provides a clear tutorial on generating code infrastructure defined OpenAPI schema for your custom Spring Boot application and handling multipart file uploads through an autogenerated REST endpoint.</p>
<p><span id="more-1360"></span></p>
<h2>Introduction</h2>
<p>Let&#8217;s imagine we want to build some simple user management app separated frontend with which we will communicate through REST.</p>
<p>Also, let&#8217;s add some limitations and requirements for our user management project. We will need to use the OpenAPI schema to generate the code infrastructure, as it can help us speed up interface development between the frontend and backend. We will focus on the implementation of code infrastructure on the backend side.</p>
<p>We generally want to receive and process multiple user files through multipart form data in Spring Boot.</p>
<h2>Maven OpenAPI plugin</h2>
<p>First, we must define a plugin in the pom.xml file to generate the code infrastructure from the OpenAPI schema.</p>
<p>Here is an example of the <em>pom.xml</em> file with the plugin definition:</p>
<pre><code class="language-xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"&gt;
  &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;

  &lt;parent&gt;
    &lt;groupId&gt;com.codepills.openapi&lt;/groupId&gt;
    &lt;artifactId&gt;spring-boot-parent&lt;/artifactId&gt;
    &lt;version&gt;1.1.0&lt;/version&gt;
  &lt;/parent&gt;

  &lt;groupId&gt;com.codepills.openapi&lt;/groupId&gt;
  &lt;artifactId&gt;user-management-module&lt;/artifactId&gt;
  &lt;version&gt;1.0.0-SNAPSHOT&lt;/version&gt;
  &lt;name&gt;user-management-module&lt;/name&gt;
  &lt;description&gt;User management module&lt;/description&gt;

  &lt;properties&gt;
    &lt;java.version&gt;21&lt;/java.version&gt;
    &lt;project.build.sourceEncoding&gt;UTF-8&lt;/project.build.sourceEncoding&gt;
    &lt;project.reporting.outputEncoding&gt;UTF-8&lt;/project.reporting.outputEncoding&gt;
    &lt;version.swagger.codegen&gt;3.0.50&lt;/version.swagger.codegen&gt;
    &lt;open.api.file&gt;${project.basedir}/src/main/api-specification/OpenApi-UserManagement.yaml&lt;/open.api.file&gt;
    &lt;open.api.base&gt;com.codepills.openapi.usermanagementmodule&lt;/open.api.base&gt;
    &lt;generated-sources-path&gt;${project.build.directory}/generated-sources&lt;/generated-sources-path&gt;
    &lt;generated-sources-java-path&gt;main/java&lt;/generated-sources-java-path&gt;
  &lt;/properties&gt;

  &lt;dependencies&gt;...&lt;/dependencies&gt;

  &lt;build&gt;
    &lt;finalName&gt;${project.name}&lt;/finalName&gt;
    &lt;plugins&gt;
      &lt;plugin&gt;
        &lt;groupId&gt;io.swagger.codegen.v3&lt;/groupId&gt;
        &lt;artifactId&gt;swagger-codegen-maven-plugin&lt;/artifactId&gt;
        &lt;version&gt;${version.swagger.codegen}&lt;/version&gt;
        &lt;executions&gt;
          &lt;execution&gt;
            &lt;id&gt;generate-the-stuff&lt;/id&gt;
            &lt;phase&gt;generate-sources&lt;/phase&gt;
            &lt;goals&gt;
              &lt;goal&gt;generate&lt;/goal&gt;
            &lt;/goals&gt;
          &lt;/execution&gt;
        &lt;/executions&gt;
        &lt;configuration&gt;
          &lt;inputSpec&gt;${open.api.file}&lt;/inputSpec&gt;
          &lt;language&gt;spring&lt;/language&gt;
          &lt;modelNameSuffix&gt;Dto&lt;/modelNameSuffix&gt;
          &lt;configOptions&gt;
            &lt;sourceFolder&gt;${generated-sources-java-path}&lt;/sourceFolder&gt;
            &lt;basePackage&gt;${open.api.base}&lt;/basePackage&gt;
            &lt;modelPackage&gt;${open.api.base}.api.model&lt;/modelPackage&gt;
            &lt;apiPackage&gt;${open.api.base}.api&lt;/apiPackage&gt;
            &lt;interfaceOnly&gt;true&lt;/interfaceOnly&gt;
            &lt;useBeanValidation&gt;true&lt;/useBeanValidation&gt;
            &lt;library&gt;spring-boot3&lt;/library&gt;
            &lt;dateLibrary&gt;custom&lt;/dateLibrary&gt;
            &lt;jakarta&gt;true&lt;/jakarta&gt;
          &lt;/configOptions&gt;
          &lt;typeMappings&gt;
            &lt;typeMapping&gt;DateTime=Instant&lt;/typeMapping&gt;
            &lt;typeMapping&gt;multipartFile=org.springframework.web.multipart.MultipartFile&lt;/typeMapping&gt;
          &lt;/typeMappings&gt;
          &lt;importMappings&gt;
            &lt;importMapping&gt;Instant=java.time.Instant&lt;/importMapping&gt;
          &lt;/importMappings&gt;
          &lt;output&gt;${generated-sources-path}&lt;/output&gt;
        &lt;/configuration&gt;
      &lt;/plugin&gt;
    &lt;/plugins&gt;
  &lt;/build&gt;

  &lt;repositories&gt;...&lt;/repositories&gt;

&lt;/project&gt;</code></pre>
<p>As you can see, we have defined the SpringBoot module, and in it, the OpenAPI file is located at <i>/src/main/API-specification/OpenApi-UserManagement.yaml</i>. The <em>OpenApi-UserManagement.yaml</em> file will also be responsible for defining generated code infrastructure.</p>
<h2>OpenAPI User management definition YAML</h2>
<p>Let&#8217;s create the <em>OpenApi-UserManagement.yaml</em> file at <i>/src/main/api-specification/</i> relative to the location of <i>pom.xml</i></p>
<pre><code class="language-yaml">openapi: 3.0.2
info:
  title: User management module
  description: User management
  version: '0.1'
  contact:
  email: optional@email.com
servers:
  - url: https://localhost:8080/api/user-management

paths:
  /users/import:
    post:
      summary: Import User files
      tags:
        - UserManagement
      operationId: importFiles
      requestBody:
        content:
          multipart/form-data:
            schema:
              properties:
                userFiles:
                  type: array
                  items:
                    type: multipartFile
      responses:
        '200':
          description: Successful operation
          content:
            application/json:
              schema:
                type: object
                additionalProperties:
                  type: array
                  items:
                    type: string
        '400':
          description: Bad Request</code></pre>
<p>As you can see, we have defined a simple endpoint for importing user files. The endpoint is defined as a <code>POST</code> request with a summary, tags, operationId, requestBody and responses.</p>
<p>It is essential to define the keywords for user files well. I picked up the <i>userFiles</i>, but you can use whatever you like. For example &#8211; simply <i>files</i>. The keyword will be used for the protocol to tie the files during transmission.</p>
<h2>User Management Controller</h2>
<p>Now, all we need to do is create a controller to implement the OpenAPI schema. User management schema name will be generated based on the tags in the OpenAPI schema.</p>
<p>Here is an example of the controller:</p>
<pre><code class="language-java">@RestController
@RequiredArgsConstructor
public class UserManagementController implements UserManagementApi {

  @Override
  public ResponseEntity&lt;Map&lt;&lt;tring, List<String&gt;&gt;&gt; importFiles(@RequestPart("userFiles") List&lt;MultipartFile> userFiles) {
    // ... your logic here ...
  }

}</code></pre>
<p>I will leave the implementation up to you as it is not the main focus of this article.</p>
<p>Again, notice the <i>userFiles</i> keyword in the method argument. It is the same as the keyword as defined in the OpenAPI schema.</p>
<h2>Testing with Postman</h2>
<p>Let&#8217;s run the app; the last thing will be testing the endpoint with Postman.</p>
<p>As it might not be stressed enough so far, the most important thing is to use the same keyword as defined in the OpenAPI schema. In our case, it is <i>userFiles</i>.</p>
<p><img decoding="async" src="https://codepills.com/wp-content/uploads/2024/02/postman_multipart_request_with_multiple_files.png" alt="Postman - Multipart request with multiple files" width="665" height="319" class="size-full wp-image-1361" srcset="https://codepills.com/wp-content/uploads/2024/02/postman_multipart_request_with_multiple_files.png 665w, https://codepills.com/wp-content/uploads/2024/02/postman_multipart_request_with_multiple_files-300x144.png 300w" sizes="(max-width: 665px) 100vw, 665px" /></p>
<p>And now, if the backend is running at localhost, and we added the necessary logic for file processing into the controller, we should be able to upload multiple files through the endpoint.</p>
<p>When using Postman, you also need to define the type of multipart key. It is either the <em>String</em> or <em>File</em>. For files, use <em>File</em>, and for the object, use <em>String</em>. The following article will discuss the <a href="https://codepills.com/how-to-make-multipart-requests-with-file-and-object-through-autogenerated-code-defined-in-openapi/" title="How to make multipart requests with file and object through autogenerated code defined in OpenAPI" target="_blank" rel="nofollow noopener">implementation and use of mixed input</a>.</p>
<p>Otherwise, all you need to do is to define your endpoint <code>POST</code> request as everything else. Select <code>POST</code> request, add the URL, and in the body tab, select form-data and add the keyword and the file.</p>
<p>Add multiple files with the same key &#8220;userFiles&#8221; and send the request.</p>
<h2>Conclusion</h2>
<p>This article has shown how to implement autogenerate of code from OpenAPI schema, how to define the schema for multiple file uploads and how to implement the endpoint at the Spring Boot backend. All you need to do is run your application and use the same keyword defined in the OpenAPI schema for the file upload.</p>
<p>Did you find autogenerate OpenAPI implementation and sending files through multipart requests easy? Do you have your trick or know another way <u> to send effectively multipart requests with files</u>? Let us know in the comments below the article. We would like to hear your ideas and stories.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://codepills.com/how-to-make-multipart-requests-with-files-through-autogenerated-code-defined-in-openapi/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>3 ways how to kill Spring Boot application at port 8080 on Windows</title>
		<link>https://codepills.com/3-ways-how-to-kill-spring-boot-application-at-port-8080-on-windows/</link>
					<comments>https://codepills.com/3-ways-how-to-kill-spring-boot-application-at-port-8080-on-windows/#respond</comments>
		
		<dc:creator><![CDATA[Andrej Buday]]></dc:creator>
		<pubDate>Wed, 03 Feb 2021 17:47:12 +0000</pubDate>
				<category><![CDATA[Bug hunt]]></category>
		<category><![CDATA[cmd]]></category>
		<category><![CDATA[computer]]></category>
		<category><![CDATA[error]]></category>
		<category><![CDATA[IDE]]></category>
		<category><![CDATA[IntelliJ Idea]]></category>
		<category><![CDATA[PID]]></category>
		<category><![CDATA[process]]></category>
		<category><![CDATA[process ID]]></category>
		<category><![CDATA[server container]]></category>
		<category><![CDATA[servlet]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[Spring Boot]]></category>
		<category><![CDATA[Spring Boot application]]></category>
		<category><![CDATA[Spring development]]></category>
		<category><![CDATA[terminal]]></category>
		<guid isPermaLink="false">https://codepills.com/?p=1132</guid>

					<description><![CDATA[This article is a simple tutorial on how to kill your Spring Boot application which occupies port 8080 on Windows <a href="https://codepills.com/3-ways-how-to-kill-spring-boot-application-at-port-8080-on-windows/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<p>This article tries to answer one of the most often occurred questions connected with Spring Boot development. When developing a web application with Spring Boot, you might hit an error announcing that port 8080 is occupied. In this article, we will see why and how to solve this error. However, be sure that tutorial can help you solve the occupancy of any other port.</p>
<p><span id="more-1132"></span></p>
<h2>Spring Boot application default port</h2>
<p>When you develop long enough with Spring Boot, you know the error very well. You work on your Spring Boot application, and you use a console for running the application. Or you use your favourite IDE runner for starting your application (my preferred IDE is IntelliJ IDEA). Your Spring Boot application in the running embedded in servlet container when suddenly you need to do something else. Instead of adequately terminating the embedded servlet container with your application, you detach from the servlet by a closing terminal window or switching to a different project in IDE. However, because you did not correctly terminate your IDE runner and did not correctly kill the terminal&#8217;s application process, the servlet with the application is still running. After that, you might, of course, start developing something else. Surprise, surprise, you cannot. Any Spring Boot application port, by default number 8080, is still occupied with the unterminated process of your Spring Boot servlet container. (In the tutorial, we assume you are using the Spring Boot application port on default port number 8080).</p>
<p>I guess you might be a little bit confused by all the wording describing the issue. Let&#8217;s take a look first at some terminology to understand the problem here fully:</p>
<h3>What is process?</h3>
<p>We are aware that readers of this blog are pretty skilled in computers. So, we will provide a brief description of what is computer process without going to further details.</p>
<p>Every time you start a program on your computer, it requires a certain amount of resource. Your Central Processor Unit, known as CPU, add to this program its process.</p>
<p>If you open task manager on your Windows, you will see a list of all process your CPU is trying to manage at once.</p>
<h3>What is process ID?</h3>
<p>The process ID, also known as PID, is the number assigned by the operating system to each new process.</p>
<h3>What is port number?</h3>
<p>A port number is how to identify individual processes for network message when they arrive on a server. In a real sense, a port number is the logical address of each application or process that helps identify the sender and receiver of processed messages. </p>
<p>You can imagine port numbers as doors in the hallway into which message flows through the networks. It leaves one door and enters another.</p>
<h3>What is Spring Boot server container?</h3>
<p>Spring Boot is a Spring project which makes Spring development fast. Without going too much into the Spring Boot project details, your Spring Boot application runs in a server container, better known as a servlet. This servlet runs in one computer process and lister on port 8080 for traffic.</p>
<h2>Restart computer</h2>
<p>One way how to solve this is to restart your computer. During the restart of Windows OS, start all the fresh, and port 8080 will be empty. But this is not the fastest and definitely not the right way for developers to solve this.</p>
<h2>Set different port number</h2>
<p>Another way is to solve this issue by assigning the Spring Boot application a different port number. When we set a different port number for the application, we will not kill the existing process with the application servlet container. However, we will create a new-different process for the servlet container, which will be listening on a different port. In this way, port 8080 will be still occupied, but we will at least be able to continue to develop.</p>
<p>Go to Spring Boot <code>application.properties</code> file and set different port number for <code>server.port</code> .</p>
<p>Despite this quick workaround, there is a much more mature way to solve this problem. I would like you to show a better way to kill a Spring Boot servlet container listening on port 8080.</p>
<h2>Kill the process listening at port 8080</h2>
<p>To kill the process listening at port 8080 in the Windows environment, we need only go through a few steps. First, check the image below to get the idea.</p>
<p><img decoding="async" src="https://codepills.com/wp-content/uploads/2021/02/kill_process_at_port_8080_on_the_windows_10.png" alt="How to kill process listening at port_8080 on the Windows 10" width="623" height="198" class="size-full wp-image-1133" srcset="https://codepills.com/wp-content/uploads/2021/02/kill_process_at_port_8080_on_the_windows_10.png 623w, https://codepills.com/wp-content/uploads/2021/02/kill_process_at_port_8080_on_the_windows_10-300x95.png 300w" sizes="(max-width: 623px) 100vw, 623px" /></p>
<h3>Find the process occupying port 8080</h3>
<p>On the Windows, open your CMD terminal. With simple command <code>netstat  -ano  |  findstr  PORT_NUMBER</code>, where for PORT_NUMBER add port number 8080, and on command prompt output (hit enter), we will get the <b>process id</b> of process <strong>listening on port 8080</strong>.</p>
<h3>Kill the process with command prompt</h3>
<p>Now, all we need to do is just type the following command <code>taskkill  /F  /PID  PROCESS_ID</code> and replace PROCESS_ID by the <b>process id</b> we got from the previous command result.</p>
<p>If you have typed everything correctly, process listening on port 8080 should be terminated.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://codepills.com/3-ways-how-to-kill-spring-boot-application-at-port-8080-on-windows/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to set a hot-swap on your Java project in IntelliJ Idea</title>
		<link>https://codepills.com/how-to-set-a-hot-swap-on-your-java-project-in-intellij-idea/</link>
					<comments>https://codepills.com/how-to-set-a-hot-swap-on-your-java-project-in-intellij-idea/#respond</comments>
		
		<dc:creator><![CDATA[Andrej Buday]]></dc:creator>
		<pubDate>Wed, 19 Aug 2020 11:44:36 +0000</pubDate>
				<category><![CDATA[IDE]]></category>
		<category><![CDATA[hotswap]]></category>
		<category><![CDATA[IntelliJ]]></category>
		<category><![CDATA[Open JDK]]></category>
		<category><![CDATA[Spring Boot]]></category>
		<category><![CDATA[Trava Open JDK]]></category>
		<category><![CDATA[windows]]></category>
		<guid isPermaLink="false">https://codepills.com/?p=1068</guid>

					<description><![CDATA[In this article, we will look at how to hot-swap changes <a href="https://codepills.com/how-to-set-a-hot-swap-on-your-java-project-in-intellij-idea/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<p>Let&#8217;s take a look at how to speed up the development of our Spring Boot app by installing Trava Open JDK and use of hot-swapping.</p>
<p><span id="more-1068"></span></p>
<h2>How to set hot swap with Trava Open JDK in your IntelliJ Idea</h2>
<ol>
<li>Install to your computer Trava Open JDK. You can find installation binaries at <a href="https://github.com/TravaOpenJDK/trava-jdk-11-dcevm" title="Download Trava Open JDK" rel="nofollow">Trava Open JDK on GitHub</a>. If you are Windows user, I would give you a tip to just download Windows binaries and unpack them to folder where you have the rest of JDKs. Exp. <i>C:/Program files/Java/</i> .</li>
<li>In IntelliJ Idea go to <i>Project Structure</i> and under <i>Platform Settings</i> add to <i>SDKs</i> Trava Open JDK. Also under <i>Project Settings</i> in <i>Project SDK</i> select Trave Open JDK as JDK for your project.</li>
<li>And as last step change in IntelliJ Spring Boot runner configuration <i>Running Application Update Policies</i>. Change <i>On &#8216;Update&#8217; action</i> and set it to <i>Update classes and resources</i> and <i>On frame deactivation</i> set the same to  <i>Update classes and resources</i>. You can check image below for more details.</li>
</ol>
<p><img loading="lazy" decoding="async" src="https://codepills.com/wp-content/uploads/2020/08/intellij_runner_with_hotswapping-886x1024.png" alt="IntelliJ runne with hot swapping" width="640" height="740" class="alignnone size-large wp-image-1069" srcset="https://codepills.com/wp-content/uploads/2020/08/intellij_runner_with_hotswapping-886x1024.png 886w, https://codepills.com/wp-content/uploads/2020/08/intellij_runner_with_hotswapping-260x300.png 260w, https://codepills.com/wp-content/uploads/2020/08/intellij_runner_with_hotswapping-768x887.png 768w, https://codepills.com/wp-content/uploads/2020/08/intellij_runner_with_hotswapping.png 900w" sizes="(max-width: 640px) 100vw, 640px" /></p>
<p>And that is all. You can start your app now, and your code will be hot-swapped on frame deactivation. Or you can command hot-swap manually with <code>ctrl + shift + f9</code>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://codepills.com/how-to-set-a-hot-swap-on-your-java-project-in-intellij-idea/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
