Thursday, November 24, 2022

Oracle JDeveloper 4K Display (3840×2160) Resolution Problem on Windows 10

 There were a lot of issues observed when running JDeveloper 12c in high resolution on Windows 10


The issues include:

  • JDeveloper Buttons, Icons, Menu are illegible
  • Fonts are too small

Issues observed in environment:

  • Windows 10 (x64)
  • Java 1.7.080
  • JDeveloper 12c (12.1.3/12.2.2.4)
  • Screen Resolution: 3840×2160 (4K)
Solution

  •  Create a shortcut for JDeveloper on desktop then right click on it; Select “Properties” and go to “Compability” tab, find “Change high DPI settings” button at bottom and click on it. 
  • Check the option “Override high DPI scaling behavior. Scaling performed by: System”. Finally click OK, click Apply!  
 



Saturday, July 16, 2022

SpringBoot API to return compressed CSV file

Here's an example of a Spring Boot Controller that accepts a request payload of type EmployeeRequest, generates a CSV file based on the input data, compresses the file into a ZIP, and returns the zipped file as a response:

 



Spring Boot Controller

java

import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVPrinter; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody; import java.io.*; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; @RestController @RequestMapping("/api/employee") public class EmployeeController { @PostMapping("/generate") public ResponseEntity<StreamingResponseBody> generateZippedCsv(@RequestBody EmployeeRequest request) { StreamingResponseBody responseBody = outputStream -> { // Create CSV in memory ByteArrayOutputStream csvOutputStream = new ByteArrayOutputStream(); try (CSVPrinter csvPrinter = new CSVPrinter(new PrintWriter(csvOutputStream), CSVFormat.DEFAULT)) { // Add CSV Headers csvPrinter.printRecord("First Name", "Last Name", "Middle Name", "Date of Birth"); // Populate CSV rows with request data for (Employee employee : request.getEmployees()) { csvPrinter.printRecord( employee.getFirstName(), employee.getLastName(), employee.getMiddleName(), employee.getDateOfBirth() ); } } // Create ZIP containing the CSV try (ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream)) { zipOutputStream.putNextEntry(new ZipEntry("employees.csv")); zipOutputStream.write(csvOutputStream.toByteArray()); zipOutputStream.closeEntry(); } }; // Set headers for ZIP file download HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); headers.set(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"employees.zip\""); return ResponseEntity.ok() .headers(headers) .body(responseBody); } }

Supporting Classes

EmployeeRequest

This class represents the input request payload that contains a list of employees.

java

import java.util.List; public class EmployeeRequest { private List<Employee> employees; // Getters and Setters public List<Employee> getEmployees() { return employees; } public void setEmployees(List<Employee> employees) { this.employees = employees; } }

Employee

This class represents the individual employee data.

java

public class Employee { private String firstName; private String lastName; private String middleName; private String dateOfBirth; // Use String for simplicity; can use LocalDate or Date instead // Getters and Setters public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getMiddleName() { return middleName; } public void setMiddleName(String middleName) { this.middleName = middleName; } public String getDateOfBirth() { return dateOfBirth; } public void setDateOfBirth(String dateOfBirth) { this.dateOfBirth = dateOfBirth; } } 
 

How It Works

  1. Input: The API receives a JSON payload containing a list of employees with their details (firstNamelastNamemiddleName, and dateOfBirth).
  2. CSV Generation: It generates a CSV file with these details in memory.
  3. ZIP Compression: The CSV file is compressed into a ZIP archive.
  4. Response: The ZIP file is returned to the client with appropriate headers for file download.

  



Example Request

POST Request

http

POST /api/employee/generate Content-Type: application/json

Request Body

json

{ "employees": [ { "firstName": "John", "lastName": "Doe", "middleName": "A.", "dateOfBirth": "1985-03-15" }, { "firstName": "Jane", "lastName": "Smith", "middleName": "B.", "dateOfBirth": "1990-07-21" } ] }

Response

The API returns a employees.zip file containing the CSV file. The CSV will look like this:

csv

First Name,Last Name,Middle Name,Date of Birth John,Doe,A.,1985-03-15 Jane,Smith,B.,1990-07-21

 

1. Spring Boot Configuration Limits

Spring Boot uses Servlet multipart handling for file uploads and responses. The maximum file size is governed by the spring.servlet.multipart properties:

  • spring.servlet.multipart.max-file-size:

    • Limits the maximum size of a single uploaded file or generated response.
    • Default: 1MB.
  • spring.servlet.multipart.max-request-size:

    • Limits the total size of all files in a multipart request or response.
    • Default: 10MB.

Example Configuration in application.properties:

properties

spring.servlet.multipart.max-file-size=100MB spring.servlet.multipart.max-request-size=100MB

2. Server-Specific Limits

Your server configuration (e.g., Tomcat, Jetty) also enforces limits:

Tomcat:

  • server.tomcat.max-swallow-size: Specifies the maximum size of a request body or response.
    • Default: 2MB.
    • Set -1 for no limit.

Example:

properties

server.tomcat.max-swallow-size=-1

Other Servers:

  • Jetty, Undertow, or other embedded servers might have similar settings for request/response size limits. Check their documentation for details.

3. JVM Memory Limits

Your application must have enough memory to handle large files, especially for:

  • In-Memory Operations: When files are stored or manipulated in memory (e.g., CSV generation or zipping).
  • Heap Space: Ensure your JVM has adequate heap memory to avoid OutOfMemoryError.

JVM Options:

bash

-Xms512M -Xmx2G

This example sets the JVM to use 512MB initial memory and 2GB maximum memory.


4. Operating System Limits

The underlying operating system may impose limits on:

  • Temporary File Storage: For file uploads or in-memory buffers, check /tmp (or equivalent) storage space.
  • Maximum Open File Handles: Ensure you are not exceeding the file descriptor limits, particularly in high-concurrency scenarios.

5. Practical Limits for Download Responses

For downloading files (like a CSV zipped file):

  • StreamingResponseBody: Use it to stream large files directly to the response output stream, avoiding in-memory buffering.
  • This approach minimizes memory usage, allowing responses to exceed typical memory constraints.

6. Network Bandwidth

Large file downloads are also affected by:

  • Network bandwidth between the server and the client.
  • Timeouts due to prolonged transfers.

Ensure:

  • Timeouts are configured appropriately (server.connection-timeout in Spring Boot).
  • Clients can handle large file downloads.

Summary

  • Default Spring Boot limits are 1MB per file and 10MB per request.
  • You can increase these limits using properties like spring.servlet.multipart.max-file-size.
  • Use StreamingResponseBody for large file downloads to avoid memory bottlenecks.
  • Monitor JVM memory, server configurations, and OS limits to ensure performance and reliability.

If you are working with extremely large files (e.g., several GB), consider a more robust solution like:

  • Direct S3 File Downloads: Upload the file to AWS S3 and share a pre-signed URL.
  • Chunked File Downloads: Break the file into smaller chunks for transmission.

Use SSH Keys to clone GIT Repository using SSH

  1. Generate a New SSH Key Pair bash ssh-keygen -t rsa -b 4096 -C "HSingh@MindTelligent.com" -t rsa specifies the type of key (...