<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Eduardo Issao Ito</title>
    <description>The latest articles on Forem by Eduardo Issao Ito (@adzubla).</description>
    <link>https://forem.com/adzubla</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F118418%2F9708cdac-3de9-447e-9c57-e29c87f96bbc.jpeg</url>
      <title>Forem: Eduardo Issao Ito</title>
      <link>https://forem.com/adzubla</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/adzubla"/>
    <language>en</language>
    <item>
      <title>Reusable Spring Boot 4 Error Handler</title>
      <dc:creator>Eduardo Issao Ito</dc:creator>
      <pubDate>Fri, 08 May 2026 13:49:57 +0000</pubDate>
      <link>https://forem.com/adzubla/reusable-spring-boot-4-error-handler-10kp</link>
      <guid>https://forem.com/adzubla/reusable-spring-boot-4-error-handler-10kp</guid>
      <description>&lt;h2&gt;
  
  
  Why use this library
&lt;/h2&gt;

&lt;p&gt;Out of the box, Spring Boot returns a plain &lt;code&gt;500 Internal Server Error&lt;/code&gt; for most&lt;br&gt;
unhandled exceptions, and its default &lt;code&gt;BasicErrorController&lt;/code&gt; produces a flat JSON&lt;br&gt;
object that varies between Spring versions and reveals internal details such as&lt;br&gt;
exception class names and stack-trace snippets. This makes it hard for API clients&lt;br&gt;
to handle errors programmatically and exposes information that should stay&lt;br&gt;
server-side.&lt;/p&gt;

&lt;p&gt;This library replaces that behaviour with a single, consistent error contract across&lt;br&gt;
every failure mode your API can encounter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Structured, machine-readable bodies.&lt;/strong&gt; Every error follows RFC 9457 Problem
Details with a stable &lt;code&gt;code&lt;/code&gt; field (e.g. &lt;code&gt;INVALID_ENUM_VALUE&lt;/code&gt;, &lt;code&gt;VALIDATION_FAILED&lt;/code&gt;,
&lt;code&gt;DUPLICATE_VALUE&lt;/code&gt;). Clients can branch on &lt;code&gt;code&lt;/code&gt; without parsing human-readable
messages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Precise field-level context.&lt;/strong&gt; JSON deserialization errors include the exact
JSONPath (&lt;code&gt;$.address.street&lt;/code&gt;), the rejected value, the expected type, and — for
enums — the full list of valid values. Validation errors list every constraint
violation in one response so clients do not need to submit the form multiple times
to discover all problems.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No internal leakage.&lt;/strong&gt; Raw database messages, exception class names, and stack
traces never reach the client. Constraint names are extracted from PostgreSQL
error messages via regex and presented as opaque codes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistent tracing.&lt;/strong&gt; The Micrometer trace ID is stamped into every error body
(&lt;code&gt;traceId&lt;/code&gt;) and onto every HTTP response (&lt;code&gt;X-Trace-Id&lt;/code&gt; header), so support teams
can correlate a client-side error report directly to a distributed trace.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Drop-in auto-configuration.&lt;/strong&gt; Package this module as a JAR and declare it as a
dependency — no &lt;code&gt;@Import&lt;/code&gt;, no &lt;code&gt;@ComponentScan&lt;/code&gt;, no boilerplate. Spring Boot picks
up the handlers automatically.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dependency&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Spring Boot 4.x&lt;/td&gt;
&lt;td&gt;Tested on 4.0.6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;spring-boot-starter-webmvc&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Required&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;spring-boot-starter-validation&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Required for &lt;code&gt;ValidationExceptionHandler&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;spring-boot-starter-data-jpa&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Required for &lt;code&gt;DataExceptionHandler&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;spring-boot-starter-actuator&lt;/code&gt; + &lt;code&gt;spring-boot-micrometer-tracing-brave&lt;/code&gt; + &lt;code&gt;micrometer-tracing-bridge-brave&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Optional — enables &lt;code&gt;traceId&lt;/code&gt; in bodies and &lt;code&gt;X-Trace-Id&lt;/code&gt; header&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  Adding the library to a project
&lt;/h2&gt;

&lt;p&gt;Copy the &lt;code&gt;com.example.demo.error&lt;/code&gt; package into your project. Spring Boot's component&lt;br&gt;
scan will pick up all &lt;code&gt;@RestControllerAdvice&lt;/code&gt; and &lt;code&gt;@Component&lt;/code&gt; beans automatically,&lt;br&gt;
provided the package is within your application's scan root.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Packaging as a reusable JAR.&lt;/strong&gt; If you extract these classes into a shared library,&lt;br&gt;
register them in&lt;br&gt;
&lt;code&gt;META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports&lt;/code&gt;&lt;br&gt;
(one fully-qualified class name per line). Spring Boot reads that file at startup and&lt;br&gt;
activates the listed classes as auto-configurations, so consumers of the JAR need no&lt;br&gt;
&lt;code&gt;@Import&lt;/code&gt; or &lt;code&gt;@ComponentScan&lt;/code&gt; — the dependency alone is sufficient.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  What's included
&lt;/h2&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;JsonExceptionHandler&lt;/code&gt; — 400 Bad Request
&lt;/h3&gt;

&lt;p&gt;Handles &lt;code&gt;HttpMessageNotReadableException&lt;/code&gt; (Jackson deserialization failures). Maps the&lt;br&gt;
Jackson 3 cause chain to a structured response:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Cause&lt;/th&gt;
&lt;th&gt;&lt;code&gt;code&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;Extra fields&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;UnrecognizedPropertyException&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;UNKNOWN_JSON_FIELD&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;path&lt;/code&gt;, &lt;code&gt;validValues&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;InvalidFormatException&lt;/code&gt; (enum)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;INVALID_ENUM_VALUE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;path&lt;/code&gt;, &lt;code&gt;invalidValue&lt;/code&gt;, &lt;code&gt;expectedType&lt;/code&gt;, &lt;code&gt;validValues&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;InvalidFormatException&lt;/code&gt; (scalar)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;INVALID_FIELD_VALUE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;path&lt;/code&gt;, &lt;code&gt;invalidValue&lt;/code&gt;, &lt;code&gt;expectedType&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MismatchedInputException&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;TYPE_MISMATCH&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;path&lt;/code&gt;, &lt;code&gt;expectedType&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;InputCoercionException&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;INTEGER_OVERFLOW&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;validRange&lt;/code&gt;, &lt;code&gt;line&lt;/code&gt;, &lt;code&gt;column&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;StreamReadException&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;MALFORMED_JSON&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;line&lt;/code&gt;, &lt;code&gt;column&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Other&lt;/td&gt;
&lt;td&gt;&lt;code&gt;MALFORMED_REQUEST_BODY&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"about:blank"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Invalid enum value"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"detail"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Cannot deserialize value 'UNKNOWN' as Category at path $.category — valid values: [ELECTRONICS, BOOKS, CLOTHING]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"instance"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/products"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"INVALID_ENUM_VALUE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"$.category"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"invalidValue"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"UNKNOWN"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"expectedType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Category"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"validValues"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"ELECTRONICS"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"BOOKS"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"CLOTHING"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"traceId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"69fcf2db21f488679d633abb34871dbb"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;ValidationExceptionHandler&lt;/code&gt; — 422 Unprocessable Content
&lt;/h3&gt;

&lt;p&gt;Handles &lt;code&gt;MethodArgumentNotValidException&lt;/code&gt; (&lt;code&gt;@Valid&lt;/code&gt; on &lt;code&gt;@RequestBody&lt;/code&gt;) and&lt;br&gt;
&lt;code&gt;HandlerMethodValidationException&lt;/code&gt; (&lt;code&gt;@Validated&lt;/code&gt; on individual parameters).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"about:blank"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Validation failed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;422&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"detail"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"One or more fields failed validation"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"instance"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/products"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"VALIDATION_FAILED"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"violations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"$.name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"invalidValue"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"must not be blank"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"$.price"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"invalidValue"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"-1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"must be greater than 0"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"traceId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"69fcf2db21f488679d633abb34871dbb"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;DataExceptionHandler&lt;/code&gt; — 404 / 409
&lt;/h3&gt;

&lt;p&gt;Handles JPA and JDBC data exceptions. Constraint names are extracted from the PostgreSQL&lt;br&gt;
error message via regex; raw database messages are never forwarded to the client.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Exception&lt;/th&gt;
&lt;th&gt;Condition&lt;/th&gt;
&lt;th&gt;&lt;code&gt;code&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DuplicateKeyException&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;any&lt;/td&gt;
&lt;td&gt;&lt;code&gt;DUPLICATE_VALUE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;409&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DataIntegrityViolationException&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;unique constraint&lt;/td&gt;
&lt;td&gt;&lt;code&gt;DUPLICATE_VALUE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;409&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DataIntegrityViolationException&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;foreign key constraint&lt;/td&gt;
&lt;td&gt;&lt;code&gt;REFERENTIAL_INTEGRITY_VIOLATION&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;409&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DataIntegrityViolationException&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;other&lt;/td&gt;
&lt;td&gt;&lt;code&gt;DATA_INTEGRITY_VIOLATION&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;409&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;EmptyResultDataAccessException&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;any&lt;/td&gt;
&lt;td&gt;&lt;code&gt;RESOURCE_NOT_FOUND&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;404&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;EntityNotFoundException&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;any&lt;/td&gt;
&lt;td&gt;&lt;code&gt;RESOURCE_NOT_FOUND&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;404&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;GlobalExceptionHandler&lt;/code&gt; — Spring MVC infrastructure + catch-all
&lt;/h3&gt;

&lt;p&gt;Extends &lt;code&gt;ResponseEntityExceptionHandler&lt;/code&gt; to handle the full set of Spring MVC exceptions&lt;br&gt;
(405, 415, 400, 404, 408, 413, …) and adds a stable &lt;code&gt;code&lt;/code&gt; field to each. A final&lt;br&gt;
&lt;code&gt;@ExceptionHandler(Exception.class)&lt;/code&gt; returns 500 &lt;code&gt;INTERNAL_SERVER_ERROR&lt;/code&gt; and logs&lt;br&gt;
the stack trace at &lt;code&gt;ERROR&lt;/code&gt; level.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;ProblemDetailTraceAdvice&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;ResponseBodyAdvice&lt;/code&gt; that appends &lt;code&gt;"traceId": "&amp;lt;hex&amp;gt;"&lt;/code&gt; to every &lt;code&gt;ProblemDetail&lt;/code&gt; body&lt;br&gt;
produced by an &lt;code&gt;@ExceptionHandler&lt;/code&gt;. Scoped to exception handlers only — normal 2xx&lt;br&gt;
responses are not intercepted.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;TraceIdResponseHeaderFilter&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;OncePerRequestFilter&lt;/code&gt; that sets an &lt;code&gt;X-Trace-Id: &amp;lt;hex&amp;gt;&lt;/code&gt; response header on &lt;strong&gt;every&lt;/strong&gt;&lt;br&gt;
response (success and error alike). Runs at &lt;code&gt;Ordered.LOWEST_PRECEDENCE&lt;/code&gt; so it is&lt;br&gt;
guaranteed to execute inside the &lt;code&gt;ServerHttpObservationFilter&lt;/code&gt; span context.&lt;/p&gt;
&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Jackson — unknown field detection
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="c"&gt;# Required for JsonExceptionHandler to produce UNKNOWN_JSON_FIELD responses.
# Without this, Jackson silently ignores unrecognised fields and the handler
# never sees an UnrecognizedPropertyException.
&lt;/span&gt;&lt;span class="py"&gt;spring.jackson.deserialization.fail-on-unknown-properties&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Tracing
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="c"&gt;# Fraction of requests that receive a trace ID (0.0–1.0).
# Defaults to 0.1 (10 %). Set to 1.0 in development so every request
# gets an X-Trace-Id header and a traceId field in error bodies.
&lt;/span&gt;&lt;span class="py"&gt;management.tracing.sampling.probability&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;1.0&lt;/span&gt;
&lt;span class="c"&gt;# Disable tracing entirely without removing the dependency.
# ProblemDetailTraceAdvice and TraceIdResponseHeaderFilter become no-ops.
# management.tracing.enabled=false
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Logging
&lt;/h3&gt;
&lt;h4&gt;
  
  
  Log levels per handler
&lt;/h4&gt;

&lt;p&gt;Each handler logs at a level that reflects the severity of the underlying problem.&lt;br&gt;
Override individual loggers to tune verbosity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="c"&gt;# JsonExceptionHandler — DEBUG for all recognised causes, WARN for unclassified bodies
&lt;/span&gt;&lt;span class="py"&gt;logging.level.com.example.demo.error.JsonExceptionHandler&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;DEBUG&lt;/span&gt;
&lt;span class="c"&gt;# ValidationExceptionHandler — DEBUG for every violation set
&lt;/span&gt;&lt;span class="py"&gt;logging.level.com.example.demo.error.ValidationExceptionHandler&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;DEBUG&lt;/span&gt;
&lt;span class="c"&gt;# DataExceptionHandler — WARN for constraint violations, DEBUG for not-found
&lt;/span&gt;&lt;span class="py"&gt;logging.level.com.example.demo.error.DataExceptionHandler&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;DEBUG&lt;/span&gt;
&lt;span class="c"&gt;# GlobalExceptionHandler — ERROR for unexpected exceptions (stack trace included),
# everything else inherited from Spring's ResponseEntityExceptionHandler (WARN)
&lt;/span&gt;&lt;span class="py"&gt;logging.level.com.example.demo.error.GlobalExceptionHandler&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;DEBUG&lt;/span&gt;
&lt;span class="c"&gt;# Suppress the stack-trace log that Spring MVC itself emits for resolved exceptions.
# Useful in production to avoid double-logging when GlobalExceptionHandler already logs.
&lt;/span&gt;&lt;span class="py"&gt;logging.level.org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;ERROR&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Stack traces at TRACE level
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;JsonExceptionHandler&lt;/code&gt; and &lt;code&gt;ValidationExceptionHandler&lt;/code&gt; deliberately split their log&lt;br&gt;
output into two statements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DEBUG&lt;/strong&gt; — a one-line summary (field path, violation count, etc.) that is safe to
enable in production without flooding logs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TRACE&lt;/strong&gt; — the full exception stack trace, logged separately via &lt;code&gt;log.trace("Stack
trace:", ex)&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means enabling DEBUG gives you actionable context for every bad request without&lt;br&gt;
stack-trace noise. Enable TRACE only when you need to inspect the Jackson or Validator&lt;br&gt;
internals (e.g. to diagnose a misconfigured deserializer):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="c"&gt;# Stack traces for JSON deserialization failures
&lt;/span&gt;&lt;span class="py"&gt;logging.level.com.example.demo.error.JsonExceptionHandler&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;TRACE&lt;/span&gt;
&lt;span class="c"&gt;# Stack traces for Bean Validation failures
&lt;/span&gt;&lt;span class="py"&gt;logging.level.com.example.demo.error.ValidationExceptionHandler&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;TRACE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;GlobalExceptionHandler.handleUnexpected&lt;/code&gt; is the exception to this pattern: it logs at&lt;br&gt;
ERROR with the exception object directly (&lt;code&gt;log.error("Unexpected error", ex)&lt;/code&gt;), so the&lt;br&gt;
stack trace is always captured for genuinely unexpected failures regardless of the&lt;br&gt;
configured level.&lt;/p&gt;
&lt;h3&gt;
  
  
  File upload size (for &lt;code&gt;PAYLOAD_TOO_LARGE&lt;/code&gt;)
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="c"&gt;# Maximum size of a single uploaded file (default: 1MB)
&lt;/span&gt;&lt;span class="py"&gt;spring.servlet.multipart.max-file-size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;10MB&lt;/span&gt;
&lt;span class="c"&gt;# Maximum size of the entire multipart request (default: 10MB)
&lt;/span&gt;&lt;span class="py"&gt;spring.servlet.multipart.max-request-size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;50MB&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;When either limit is exceeded Spring throws &lt;code&gt;MaxUploadSizeExceededException&lt;/code&gt;, which&lt;br&gt;
&lt;code&gt;GlobalExceptionHandler&lt;/code&gt; maps to 413 &lt;code&gt;PAYLOAD_TOO_LARGE&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Internationalisation (i18n)
&lt;/h2&gt;

&lt;p&gt;Every &lt;code&gt;title&lt;/code&gt; and &lt;code&gt;detail&lt;/code&gt; field in the error body is resolved through Spring's &lt;code&gt;MessageSource&lt;/code&gt;,&lt;br&gt;
with the locale read from &lt;code&gt;LocaleContextHolder&lt;/code&gt; at exception-handling time. Translating error&lt;br&gt;
messages to a new language requires only a properties file — no code changes.&lt;/p&gt;
&lt;h3&gt;
  
  
  Bundled locales
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;File&lt;/th&gt;
&lt;th&gt;Locale&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;messages.properties&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;English (fallback)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;messages_pt_BR.properties&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Portuguese — Brazil&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  Adding a locale
&lt;/h3&gt;

&lt;p&gt;Create &lt;code&gt;messages_&amp;lt;language&amp;gt;[_&amp;lt;COUNTRY&amp;gt;].properties&lt;/code&gt; alongside the existing files and translate&lt;br&gt;
every key. Spring resolves the closest-matching bundle for the request locale automatically.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="c"&gt;# src/main/resources/messages_es.properties
&lt;/span&gt;&lt;span class="py"&gt;error.validation-failed.title&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Validación fallida&lt;/span&gt;
&lt;span class="py"&gt;error.validation-failed.detail&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Uno o más campos no pasaron la validación&lt;/span&gt;
&lt;span class="py"&gt;error.resource-not-found.title&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Recurso no encontrado&lt;/span&gt;
&lt;span class="py"&gt;error.resource-not-found.detail&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;El recurso solicitado no fue encontrado.&lt;/span&gt;
&lt;span class="c"&gt;# … remaining keys …
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you package this library as a JAR and your application defines its own &lt;code&gt;messages.properties&lt;/code&gt;,&lt;br&gt;
list both basenames so Spring merges them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;spring.messages.basename&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;messages,classpath:com/example/demo/error/messages&lt;/span&gt;
&lt;span class="py"&gt;spring.messages.encoding&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;UTF-8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Locale resolution
&lt;/h3&gt;

&lt;p&gt;By default, Spring MVC's &lt;code&gt;AcceptHeaderLocaleResolver&lt;/code&gt; maps the &lt;code&gt;Accept-Language&lt;/code&gt; request header&lt;br&gt;
to a &lt;code&gt;java.util.Locale&lt;/code&gt;. When the header is absent or no bundle matches, Spring falls back to the&lt;br&gt;
JVM default locale and then to the root &lt;code&gt;messages.properties&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To resolve locale from a cookie or session instead, declare a &lt;code&gt;LocaleResolver&lt;/code&gt; bean:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;
&lt;span class="nd"&gt;@Bean&lt;/span&gt;
&lt;span class="nc"&gt;LocaleResolver&lt;/span&gt; &lt;span class="nf"&gt;localeResolver&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;resolver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CookieLocaleResolver&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"lang"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;resolver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setDefaultLocale&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Locale&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ENGLISH&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;resolver&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Validation constraint messages
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;violations[].message&lt;/code&gt; field inside &lt;code&gt;VALIDATION_FAILED&lt;/code&gt; responses comes from &lt;strong&gt;Bean&lt;br&gt;
Validation&lt;/strong&gt;, not from the &lt;code&gt;MessageSource&lt;/code&gt; above. To localise constraint messages, add a&lt;br&gt;
&lt;code&gt;ValidationMessages_&amp;lt;locale&amp;gt;.properties&lt;/code&gt; file to your classpath:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="c"&gt;# src/main/resources/ValidationMessages_pt_BR.properties
&lt;/span&gt;&lt;span class="py"&gt;jakarta.validation.constraints.NotBlank.message&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;não deve estar em branco&lt;/span&gt;
&lt;span class="py"&gt;jakarta.validation.constraints.Size.message&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;o tamanho deve estar entre {min} e {max}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bean Validation resolves its bundle against the JVM default locale. To drive it from the&lt;br&gt;
per-request locale, supply a locale-aware &lt;code&gt;MessageInterpolator&lt;/code&gt; in your validator configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Full dependency block for tracing support
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;  &lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.springframework.boot&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;spring-boot-starter-actuator&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.springframework.boot&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;spring-boot-micrometer-tracing-brave&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;io.micrometer&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;micrometer-tracing-bridge-brave&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Without these dependencies the &lt;code&gt;traceId&lt;/code&gt; body field and &lt;code&gt;X-Trace-Id&lt;/code&gt; header are simply&lt;br&gt;
absent. All other error-handling behaviour is unaffected.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Error code reference
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;code&gt;code&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MALFORMED_JSON&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;400&lt;/td&gt;
&lt;td&gt;Syntactically invalid JSON&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MALFORMED_REQUEST_BODY&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;400&lt;/td&gt;
&lt;td&gt;Body unreadable (unclassified)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;UNKNOWN_JSON_FIELD&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;400&lt;/td&gt;
&lt;td&gt;Field not declared on the target type&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;INVALID_ENUM_VALUE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;400&lt;/td&gt;
&lt;td&gt;Value not in enum constants&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;INVALID_FIELD_VALUE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;400&lt;/td&gt;
&lt;td&gt;Value cannot be coerced to target type&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TYPE_MISMATCH&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;400&lt;/td&gt;
&lt;td&gt;Wrong JSON token type for target&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;INTEGER_OVERFLOW&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;400&lt;/td&gt;
&lt;td&gt;Numeric value outside type range&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;VALIDATION_FAILED&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;422&lt;/td&gt;
&lt;td&gt;Bean Validation constraint failure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;METHOD_VALIDATION_ERROR&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;422&lt;/td&gt;
&lt;td&gt;Method-level validation failure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DUPLICATE_VALUE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;409&lt;/td&gt;
&lt;td&gt;Unique constraint violated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;REFERENTIAL_INTEGRITY_VIOLATION&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;409&lt;/td&gt;
&lt;td&gt;Foreign key constraint violated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DATA_INTEGRITY_VIOLATION&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;409&lt;/td&gt;
&lt;td&gt;Other integrity constraint violated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;RESOURCE_NOT_FOUND&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;404&lt;/td&gt;
&lt;td&gt;Entity or query result not found&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;METHOD_NOT_ALLOWED&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;405&lt;/td&gt;
&lt;td&gt;HTTP method not supported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;UNSUPPORTED_MEDIA_TYPE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;415&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;Content-Type&lt;/code&gt; not accepted&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;NOT_ACCEPTABLE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;406&lt;/td&gt;
&lt;td&gt;Requested &lt;code&gt;Accept&lt;/code&gt; type unavailable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MISSING_PATH_VARIABLE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;400&lt;/td&gt;
&lt;td&gt;Required path variable absent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MISSING_REQUEST_PARAMETER&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;400&lt;/td&gt;
&lt;td&gt;Required query parameter absent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MISSING_REQUEST_PART&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;400&lt;/td&gt;
&lt;td&gt;Required multipart part absent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;REQUEST_BINDING_ERROR&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;400&lt;/td&gt;
&lt;td&gt;Servlet request binding failure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ROUTE_NOT_FOUND&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;404&lt;/td&gt;
&lt;td&gt;No handler mapped for the request path&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;REQUEST_TIMEOUT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;503&lt;/td&gt;
&lt;td&gt;Async request timed out&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PAYLOAD_TOO_LARGE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;413&lt;/td&gt;
&lt;td&gt;Upload exceeds configured limit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CONVERSION_NOT_SUPPORTED&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;500&lt;/td&gt;
&lt;td&gt;No converter for property type&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PARAMETER_TYPE_MISMATCH&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;400&lt;/td&gt;
&lt;td&gt;Query/path parameter type coercion failed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MESSAGE_NOT_WRITABLE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;500&lt;/td&gt;
&lt;td&gt;Response body could not be serialised&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;INTERNAL_SERVER_ERROR&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;500&lt;/td&gt;
&lt;td&gt;Unexpected exception&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Source code
&lt;/h2&gt;

&lt;p&gt;The source code of the these handlers is available in GitHub:&lt;br&gt;
&lt;a href="https://github.com/adzubla/springboot4-error-handler" rel="noopener noreferrer"&gt;https://github.com/adzubla/springboot4-error-handler&lt;/a&gt;&lt;/p&gt;

</description>
      <category>springboot</category>
      <category>errorhandler</category>
      <category>problemdetails</category>
      <category>rfc9457</category>
    </item>
    <item>
      <title>Resumo Kubernetes</title>
      <dc:creator>Eduardo Issao Ito</dc:creator>
      <pubDate>Tue, 25 Mar 2025 12:56:31 +0000</pubDate>
      <link>https://forem.com/adzubla/resumo-kubernetes-48hn</link>
      <guid>https://forem.com/adzubla/resumo-kubernetes-48hn</guid>
      <description>&lt;h2&gt;
  
  
  Configurar cluster
&lt;/h2&gt;

&lt;p&gt;Configurar kubectl para acessar um Azure AKS&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az aks get-credentials &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GROUP&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CLUSTER&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ver configurações do kubectl&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl config view
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adicionando um novo cluster ao kubectl&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Add a user/principal that will be used when connecting to the cluster&lt;/span&gt;
kubectl config set-credentials kubeuser/foo.com &lt;span class="nt"&gt;--username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubeuser &lt;span class="nt"&gt;--password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubepassword

&lt;span class="c"&gt;# Point to a cluster&lt;/span&gt;
kubectl config set-cluster foo.com &lt;span class="nt"&gt;--insecure-skip-tls-verify&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="nt"&gt;--server&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://foo.com

&lt;span class="c"&gt;# This context points to the cluster with a specific user&lt;/span&gt;
kubectl config set-context default/foo.com/kubeuser &lt;span class="nt"&gt;--user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kubeuser/foo.com &lt;span class="nt"&gt;--namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;default &lt;span class="nt"&gt;--cluster&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;foo.com

&lt;span class="c"&gt;# Use this specific context&lt;/span&gt;
kubectl config use-context default/foo.com/kubeuser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Trocando de cluster&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#  Mostrando os clusters configurados no ~/.kube&lt;/span&gt;
kubectl config get-contexts

&lt;span class="c"&gt;# Mostrando o contexto atual&lt;/span&gt;
kubectl config current-context

&lt;span class="c"&gt;# Trocando de contexto&lt;/span&gt;
kubectl config use-context CONTEXT_NAME
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Namespaces
&lt;/h2&gt;

&lt;p&gt;Criando um namespace&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl create namespace &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NAMESPACE&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Listando os namespaces existentes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get namespaces
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Trocando o namespace corrente&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl config set-context &lt;span class="nt"&gt;--current&lt;/span&gt; &lt;span class="nt"&gt;--namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NAMESPACE&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Pods
&lt;/h2&gt;

&lt;p&gt;Procurar (por label)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get pods &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;MY-APP

&lt;span class="nv"&gt;POD_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;kubectl get pods &lt;span class="nt"&gt;-o&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.items[?(@.metadata.labels.app=="MY-APP")].metadata.name}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Describe (ver eventos)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl describe pod &lt;span class="nv"&gt;$POD_NAME&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Logs (da aplicação)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl logs &lt;span class="nv"&gt;$POD_NAME&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mostrar os nodes de execução dos pods&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get pods &lt;span class="nt"&gt;-o&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;wide

&lt;span class="c"&gt;# Filtrar pelo nome do node&lt;/span&gt;
kubectl get pods &lt;span class="nt"&gt;--field-selector&lt;/span&gt; spec.nodeName&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$NODE_NAME&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Terminal
&lt;/h2&gt;

&lt;p&gt;Abrir terminal num pod&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;--stdin&lt;/span&gt; &lt;span class="nt"&gt;--tty&lt;/span&gt; &lt;span class="nv"&gt;$POD_NAME&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; /bin/bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Se estiver usando um terminal Git-bash ou MinGW, colocar a variável &lt;code&gt;MSYS_NO_PATHCONV&lt;/code&gt;:&lt;/p&gt;


&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;MSYS_NO_PATHCONV&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;--stdin&lt;/span&gt; &lt;span class="nt"&gt;--tty&lt;/span&gt; &lt;span class="nv"&gt;$POD_NAME&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; /bin/bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Service
&lt;/h2&gt;

&lt;p&gt;Acessando um serviço&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get svc &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SERVICE_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;EXTERNAL_IP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;kubectl get svc &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SERVICE_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.status.loadBalancer.ingress[0].ip}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

curl http: &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;EXTERNAL_IP&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/api/v1/hello
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expondo um endereço:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl port-forward service/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SERVICE_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; 9200:9200
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Logs
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl logs &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nv"&gt;$POD&lt;/span&gt; &lt;span class="nt"&gt;--all-containers&lt;/span&gt; &lt;span class="nt"&gt;--previous&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Restart pods
&lt;/h2&gt;

&lt;p&gt;Sem downtime:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl rollout restart deployment &amp;lt;deployment_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Parando todos pods e depois reiniciando todos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl scale deployment &amp;lt;deployment name&amp;gt; - &lt;span class="nv"&gt;replicas&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0
kubectl scale deployment &amp;lt;deployment name&amp;gt; - &lt;span class="nv"&gt;replicas&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alterando uma variável associada ao pod:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nb"&gt;set env &lt;/span&gt;deployment &amp;lt;deployment name&amp;gt; &lt;span class="nv"&gt;LAST_START_DATE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Selecionando um pod específico:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl delete pod &amp;lt;pod_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Selecionando todos pods com label:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl delete pod &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="s2"&gt;"app:myapp"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Performance
&lt;/h2&gt;

&lt;p&gt;Mostra consumo de CPU e MEMORY de pods&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl top pod
kubectl top pod POD_ID
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>kubernetes</category>
      <category>k8s</category>
      <category>kubectl</category>
      <category>aks</category>
    </item>
    <item>
      <title>Check for newer versions of dependencies in pom.xml</title>
      <dc:creator>Eduardo Issao Ito</dc:creator>
      <pubDate>Wed, 08 May 2024 22:59:30 +0000</pubDate>
      <link>https://forem.com/adzubla/check-for-newer-versions-of-dependencies-in-pomxml-21n3</link>
      <guid>https://forem.com/adzubla/check-for-newer-versions-of-dependencies-in-pomxml-21n3</guid>
      <description>&lt;p&gt;I made a script in Groovy language to look for newer versions of all declared dependencies in a Maven project. The script supports multi-module projects.&lt;/p&gt;

&lt;p&gt;It searches the current folder for pom.xml files and checks the central.sonatype.com website for a newer versions. Only dependencies that have an explicit version defined in pom will be checked. Versions defined by properties will be resolved if the properties were declared in one of the pom files. (If a property is defined more than once, the result is undefined.)&lt;/p&gt;

&lt;p&gt;Example of use:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F95e2w8fgurxn2p3e5bk5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F95e2w8fgurxn2p3e5bk5.png" alt="check-versions.sh example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I recommend installing Java 17 (or newer) and Groovy 4 with sdkman!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Put these two files in a folder that is included in PATH.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;check-versions.sh&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="nv"&gt;BASEDIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;unset &lt;/span&gt;CDPATH&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;dirname&lt;/span&gt; &lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="nv"&gt;JAVA_VER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;java &lt;span class="nt"&gt;-version&lt;/span&gt; 2&amp;gt;&amp;amp;1 | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="s1"&gt;'"'&lt;/span&gt; &lt;span class="s1"&gt;'/version/ {print $2}'&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="s1"&gt;'.'&lt;/span&gt; &lt;span class="s1"&gt;'{sub("^$", "0", $2); print $1$2}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$JAVA_VER&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-lt&lt;/span&gt; 170 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Java 17 necessario"&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;#$PROXY="-DproxySet=true -DproxyHost=10.0.0.24 -DproxyPort=8080"&lt;/span&gt;

groovy &lt;span class="nt"&gt;-Dgroovy&lt;/span&gt;.grape.report.downloads&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="nv"&gt;$PROXY&lt;/span&gt; &lt;span class="nv"&gt;$BASEDIR&lt;/span&gt;/check-versions.groovy 2&amp;gt;/dev/null


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;check-versions.groovy&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;groovy.json.JsonSlurper&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;groovy.xml.XmlParser&lt;/span&gt;
&lt;span class="nd"&gt;@Grab&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'org.jodd:jodd-lagarto:6.0.6'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jodd.jerry.Jerry&lt;/span&gt;
&lt;span class="nd"&gt;@Grab&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'org.fusesource.jansi:jansi:2.4.1'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.fusesource.jansi.AnsiConsole&lt;/span&gt;
&lt;span class="nd"&gt;@Grab&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'org.slf4j:slf4j-jdk-platform-logging:2.0.13'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.slf4j.Logger&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;static&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fusesource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jansi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Ansi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;GREEN&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;static&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fusesource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jansi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Ansi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;RED&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;static&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fusesource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jansi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Ansi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ansi&lt;/span&gt;

&lt;span class="n"&gt;AnsiConsole&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;systemInstall&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;

&lt;span class="kd"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;Dependency&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;groupId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;artifactId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;

&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;findAllDependencies&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//println("-- findAllDependencies")&lt;/span&gt;
    &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;allDeps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;
    &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;mvnProperties&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[:]&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;File&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"."&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;traverse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;type:&lt;/span&gt; &lt;span class="n"&gt;groovy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;io&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;FileType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;FILES&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;nameFilter:&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="s"&gt;/pom.xml/&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;processPom&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;XmlParser&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;parse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="n"&gt;allDeps&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mvnProperties&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;allDeps&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;unique&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;sort&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;k1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k2&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;k1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;groupId&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;k1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;artifactId&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;k2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;groupId&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;k2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;artifactId&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;processPom&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;allDeps&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;mvnProperties&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;collectProperties&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mvnProperties&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;collectDependencies&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;'**'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dependency&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;allDeps&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mvnProperties&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;collectDependencies&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;parent&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;allDeps&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mvnProperties&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;collectDependencies&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;'**'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;plugin&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;allDeps&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mvnProperties&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;collectProperties&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;mvnProperties&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//println("-- collectProperties")&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;children&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;localPart&lt;/span&gt;
            &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;mvnProperties&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;collectDependencies&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;dependencies&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;allDeps&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;mvnProperties&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//println("-- collectDependencies")&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;dependencies&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;groupId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;groupId&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;groupId&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isEmpty&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// assume default groupId for maven plugins&lt;/span&gt;
            &lt;span class="n"&gt;groupId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"org.apache.maven.plugins"&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;artifactId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;artifactId&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isEmpty&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;
        &lt;span class="nf"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;startsWith&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"\$"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;matcher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="s"&gt;/\$\{(.+?)\}/&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;matcher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;find&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;property&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;matcher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;group&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mvnProperties&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;property&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;continue&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dependency&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;groupId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;artifactId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;allDeps&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * This method is highly dependable on the html format returned by central.sonatype.com
 *
 * Return this map:
 * [name:logstash-logback-encoder, namespace:net.logstash.logback, version:7.4, versions:[7.4, 7.3, 7.2, 7.1.1, 7.1, 7.0.1, 7.0, 6.6, 6.5, 6.4, 6.3, 6.2, 6.1, 6.0, 5.3, 5.2, 5.1, 5.0, 4.11, 4.10], tags:[], usedIn:1600, tab:versions]
 */&lt;/span&gt;
&lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;findLatestVersion&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;groupId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;artifactId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//println("-- findLatestVersion ${groupId}:${artifactId}")&lt;/span&gt;
    &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"https://central.sonatype.com/artifact/${groupId}/${artifactId}/versions"&lt;/span&gt;
    &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toURL&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getText&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Jerry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;scripts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;find&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'html.nx-html.nx-html--page-scrolling body.nx-body script'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

    &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
    &lt;span class="n"&gt;scripts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;each&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'self.__next_f.push'&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;indexOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;':'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lastIndexOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'"'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;substring&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;replaceAll&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'\\\\"'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'"'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;replaceAll&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'\\\\"'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'"'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

    &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;JsonSlurper&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;parseText&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="na"&gt;children&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;ignored&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;//skipVersions = [:]&lt;/span&gt;
&lt;span class="n"&gt;skipVersions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;
        &lt;span class="s2"&gt;"org.springframework.boot:spring-boot-starter-parent"&lt;/span&gt;  &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"3.2"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"org.springframework.boot:spring-boot-starter-data-jpa"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"3.2"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"org.springframework.boot:spring-boot-starter-web"&lt;/span&gt;     &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"3.2"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"org.springframework.boot:spring-boot-dependencies"&lt;/span&gt;    &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"3.2"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"org.springframework.cloud:spring-cloud-dependencies"&lt;/span&gt;  &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2023"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;]&lt;/span&gt;

&lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;getLatestVersion&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;groupId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;artifactId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//println("-- getLatestVersion")&lt;/span&gt;
    &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;versions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;findLatestVersion&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;groupId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;artifactId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;skip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;skipVersions&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"${groupId}:${artifactId}"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;skip&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;versions&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;version&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;versions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;versions&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;startsWith&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;skip&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;allDeps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;findAllDependencies&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;allDeps&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;latest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getLatestVersion&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;groupId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;artifactId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;latest&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;continue&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"${d.groupId}:${d.artifactId}:${d.version} "&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;latest&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"${ansi().fg(GREEN)}[OK]${ansi().reset()}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"${ansi().fg(RED)}[${latest}]${ansi().reset()}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;By changing the &lt;code&gt;skipVersions&lt;/code&gt; variable, it is possible to ignore a version of some dependencies.&lt;/p&gt;

&lt;p&gt;For example: I'm stuck with Spring Boot 3.1, so the config below will ignore version 3.2, but will still notify for newer 3.1.x version.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;

&lt;span class="n"&gt;skipVersions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;
        &lt;span class="s2"&gt;"org.springframework.boot:spring-boot-starter-parent"&lt;/span&gt;  &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"3.2"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"org.springframework.boot:spring-boot-starter-data-jpa"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"3.2"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"org.springframework.boot:spring-boot-starter-web"&lt;/span&gt;     &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"3.2"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"org.springframework.boot:spring-boot-dependencies"&lt;/span&gt;    &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"3.2"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"org.springframework.cloud:spring-cloud-dependencies"&lt;/span&gt;  &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2023"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;]&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If there is no dependency to skip, just use an empty map:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;

&lt;span class="n"&gt;skipVersions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[:]&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>maven</category>
      <category>groovy</category>
    </item>
    <item>
      <title>Changing the JVM in spring-boot:build-image</title>
      <dc:creator>Eduardo Issao Ito</dc:creator>
      <pubDate>Wed, 12 Apr 2023 17:46:04 +0000</pubDate>
      <link>https://forem.com/adzubla/changing-the-jvm-in-spring-bootbuild-image-2od6</link>
      <guid>https://forem.com/adzubla/changing-the-jvm-in-spring-bootbuild-image-2od6</guid>
      <description>&lt;p&gt;The spring-boot-maven-plugin can create an OCI image from a jar or war file using Cloud Native Buildpacks.&lt;/p&gt;

&lt;p&gt;By default it uses a buildpack called &lt;code&gt;paketo-buildpacks/bellsoft-liberica&lt;/code&gt; which is based on &lt;a href="https://bell-sw.com/libericajdk/"&gt;Bellsoft Liberica JDK&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The list of all Java buildpacks is available in &lt;a href="https://paketo.io/docs/howto/java/#use-an-alternative-jvm"&gt;Paketo Buildpacks Reference&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To choose another JVM in spring-boot-maven-plugin, first you need to find the buildpacks that are used by default. Run &lt;code&gt;mvn spring-boot:build-image&lt;/code&gt; and look for something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[INFO]     [creator]     ===&amp;gt; DETECTING
[INFO]     [creator]     6 of 26 buildpacks participating
[INFO]     [creator]     paketo-buildpacks/ca-certificates   3.6.1
[INFO]     [creator]     paketo-buildpacks/bellsoft-liberica 10.1.0
[INFO]     [creator]     paketo-buildpacks/syft              1.27.0
[INFO]     [creator]     paketo-buildpacks/executable-jar    6.6.3
[INFO]     [creator]     paketo-buildpacks/dist-zip          5.5.2
[INFO]     [creator]     paketo-buildpacks/spring-boot       5.23.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That´s the list of buildpacks being used. We need to change Bellsoft Liberica to the desired JVM.&lt;/p&gt;

&lt;p&gt;So, to use &lt;a href="https://github.com/paketo-buildpacks/microsoft-openjdk"&gt;Microsoft OpenJDK&lt;/a&gt;, copy the buildpacks from above, but change &lt;code&gt;paketo-buildpacks/bellsoft-liberica&lt;/code&gt; to &lt;code&gt;gcr.io/paketo-buildpacks/microsoft-openjdk&lt;/code&gt;. The &lt;code&gt;pom.xml&lt;/code&gt; should be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;plugin&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.springframework.boot&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;spring-boot-maven-plugin&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;configuration&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;image&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;buildpacks&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;buildpack&amp;gt;&lt;/span&gt;paketo-buildpacks/ca-certificates&lt;span class="nt"&gt;&amp;lt;/buildpack&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;buildpack&amp;gt;&lt;/span&gt;gcr.io/paketo-buildpacks/microsoft-openjdk&lt;span class="nt"&gt;&amp;lt;/buildpack&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;buildpack&amp;gt;&lt;/span&gt;paketo-buildpacks/syft&lt;span class="nt"&gt;&amp;lt;/buildpack&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;buildpack&amp;gt;&lt;/span&gt;paketo-buildpacks/executable-jar&lt;span class="nt"&gt;&amp;lt;/buildpack&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;buildpack&amp;gt;&lt;/span&gt;paketo-buildpacks/dist-zip&lt;span class="nt"&gt;&amp;lt;/buildpack&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;buildpack&amp;gt;&lt;/span&gt;paketo-buildpacks/spring-boot&lt;span class="nt"&gt;&amp;lt;/buildpack&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/buildpacks&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/image&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/configuration&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/plugin&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, run &lt;code&gt;mvn spring-boot:build-image&lt;/code&gt; and verify that Microsoft OpenJDK is being used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[INFO]     [creator]     Paketo Buildpack for Microsoft OpenJDK 3.0.1
[INFO]     [creator]       https://github.com/paketo-buildpacks/microsoft-openjdk
...
[INFO]     [creator]       Microsoft OpenJDK 17.0.6: Contributing to layer
[INFO]     [creator]         Downloading from https://aka.ms/download-jdk/microsoft-jdk-17.0.6-linux-x64.tar.gz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>springbootmavenplugin</category>
      <category>springboot</category>
      <category>buildpack</category>
      <category>docker</category>
    </item>
    <item>
      <title>Changing the base Linux image in spring-boot:build-image</title>
      <dc:creator>Eduardo Issao Ito</dc:creator>
      <pubDate>Wed, 12 Apr 2023 16:59:12 +0000</pubDate>
      <link>https://forem.com/adzubla/changing-the-base-linux-image-in-spring-bootbuild-imag-1olh</link>
      <guid>https://forem.com/adzubla/changing-the-base-linux-image-in-spring-bootbuild-imag-1olh</guid>
      <description>&lt;p&gt;The spring-boot-maven-plugin can create an OCI image from a jar or war file using Cloud Native Buildpacks.&lt;/p&gt;

&lt;p&gt;By default it uses a builder called &lt;code&gt;paketobuildpacks/builder:base&lt;/code&gt; which is based on Ubuntu 18.04 and is suitable for running a Spring Boot application.&lt;/p&gt;

&lt;p&gt;But you can choose another builder, for example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;paketobuildpacks/builder:tiny&lt;/code&gt; is a lot smaller because it has the minimum requirements to run you application, even &lt;code&gt;sh&lt;/code&gt; is absent (you can't open a terminal in this image)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;paketobuildpacks/builder:full&lt;/code&gt; its the oposite of tiny, containing a lot of tools and commands.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;paketobuildpacks/builder-jammy-base&lt;/code&gt; is based on Ubuntu 22.04&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The list of all builders is available in &lt;a href="https://paketo.io/docs/reference/builders-reference/"&gt;Paketo Builders Reference&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It's just a matter of configuring the builder in &lt;code&gt;pom.xml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;plugin&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.springframework.boot&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;spring-boot-maven-plugin&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;configuration&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;image&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;builder&amp;gt;&lt;/span&gt;paketobuildpacks/builder-jammy-tiny&lt;span class="nt"&gt;&amp;lt;/builder&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/image&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/configuration&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/plugin&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>springbootmavenplugin</category>
      <category>springboot</category>
      <category>buildpack</category>
      <category>docker</category>
    </item>
    <item>
      <title>Custom Root CA in spring-boot:build-image</title>
      <dc:creator>Eduardo Issao Ito</dc:creator>
      <pubDate>Wed, 12 Apr 2023 14:46:48 +0000</pubDate>
      <link>https://forem.com/adzubla/custom-root-ca-in-spring-bootbuild-image-n2c</link>
      <guid>https://forem.com/adzubla/custom-root-ca-in-spring-bootbuild-image-n2c</guid>
      <description>&lt;p&gt;The Spring Framework has a very useful feature which is the generation of a docker image through the spring-boot-maven-plugin. Simply running &lt;code&gt;mvn spring-boot:build-image&lt;/code&gt; will create a docker compatible OCI image.&lt;/p&gt;

&lt;p&gt;But if you are behind a corporate proxy, this error is likely to happen:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[INFO]     [creator]       BellSoft Liberica JRE 17.0.6: Contributing to layer

[INFO]     [creator]         Downloading from https://github.com/bell-sw/Liberica/releases/download/17.0.6+10/bellsoft-jre17.0.6+10-linux-amd64.tar.gz

[INFO]     [creator]     unable to invoke layer creator

[INFO]     [creator]     unable to get dependency jre

[INFO]     [creator]     unable to download https://github.com/bell-sw/Liberica/releases/download/17.0.6+10/bellsoft-jre17.0.6+10-linux-amd64.tar.gz

[INFO]     [creator]     unable to request https://github.com/bell-sw/Liberica/releases/download/17.0.6+10/bellsoft-jre17.0.6+10-linux-amd64.tar.gz

[INFO]     [creator]     Get https://github.com/bell-sw/Liberica/releases/download/17.0.6+10/bellsoft-jre17.0.6+10-linux-amd64.tar.gz: x509: certificate signed by unknown authority

[INFO]     [creator]     ERROR: failed to build: exit status 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This happens because the corporation's certificate used in the proxy server is not known by the build process. When the buildpack tries download needed artifacts used inside the build process, it stops because the certificate is not trusted.&lt;/p&gt;

&lt;p&gt;spring-boot-maven-plugin uses &lt;a href="https://buildpacks.io/"&gt;Cloud Native Buildpacks&lt;/a&gt; under the hood, and it allows some &lt;a href="https://docs.spring.io/spring-boot/docs/current/maven-plugin/reference/htmlsingle/#build-image"&gt;customization&lt;/a&gt; of the build process.&lt;/p&gt;

&lt;p&gt;We need to put our corporate root CA certificates into the buildpack. For this we will create the files &lt;code&gt;mycert.cer&lt;/code&gt; and &lt;code&gt;type&lt;/code&gt; in the structure below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── pom.xml
└── src
    └── main
        └── bindings
            └── ca-certificates
                ├── mycert.cer
                └── type
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;src/main/bindings/ca-certificates/mycert.cer&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-----BEGIN CERTIFICATE-----
Base64–encoded certificate
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
Base64–encoded certificate
-----END CERTIFICATE-----
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;src/main/bindings/ca-certificates/type&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ca-certificates
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following Maven configuration will add the certificate to the buildpack.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pom.xml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;plugin&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.springframework.boot&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;spring-boot-maven-plugin&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;configuration&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;image&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;env&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;SERVICE_BINDING_ROOT&amp;gt;&lt;/span&gt;/bindings&lt;span class="nt"&gt;&amp;lt;/SERVICE_BINDING_ROOT&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/env&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;bindings&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;binding&amp;gt;&lt;/span&gt;${project.basedir}/src/main/bindings/ca-certificates:/bindings/ca-certificates&lt;span class="nt"&gt;&amp;lt;/binding&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/bindings&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/image&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/configuration&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/plugin&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, &lt;code&gt;mvn spring-boot:build-image&lt;/code&gt; should work!&lt;/p&gt;

</description>
      <category>springbootmavenplugin</category>
      <category>springboot</category>
      <category>buildpack</category>
      <category>docker</category>
    </item>
    <item>
      <title>Getting http status in curl</title>
      <dc:creator>Eduardo Issao Ito</dc:creator>
      <pubDate>Tue, 24 May 2022 19:43:58 +0000</pubDate>
      <link>https://forem.com/adzubla/getting-http-status-in-curl-4ep4</link>
      <guid>https://forem.com/adzubla/getting-http-status-in-curl-4ep4</guid>
      <description>&lt;p&gt;How to get the http status code of curl in a script?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
my_curl&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;Red&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\033[0;31m'&lt;/span&gt;
  &lt;span class="nv"&gt;Green&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\033[0;32m'&lt;/span&gt;
  &lt;span class="nv"&gt;Color_Off&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\033[0m'&lt;/span&gt;

  &lt;span class="nv"&gt;TEMP_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt; &lt;span class="nb"&gt;mktemp&lt;/span&gt; &lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;trap&lt;/span&gt; &lt;span class="s2"&gt;"rm -f &lt;/span&gt;&lt;span class="nv"&gt;$TEMP_FILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; EXIT
  curl &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;%{http_code}"&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TEMP_FILE&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
  &lt;span class="nv"&gt;body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TEMP_FILE&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'$d'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TEMP_FILE&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s1"&gt;'$p'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 2&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nv"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$Green&lt;/span&gt;
  &lt;span class="k"&gt;else
    &lt;/span&gt;&lt;span class="nv"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$Red&lt;/span&gt;
  &lt;span class="k"&gt;fi

  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;Color&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;Status: &lt;/span&gt;&lt;span class="nv"&gt;$status&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;Color_Off&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$body&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

my_curl &lt;span class="nt"&gt;-X&lt;/span&gt; GET http://jservice.io/api/random
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>bash</category>
      <category>curl</category>
    </item>
    <item>
      <title>DB2 backup/restore schema</title>
      <dc:creator>Eduardo Issao Ito</dc:creator>
      <pubDate>Thu, 14 Apr 2022 13:07:58 +0000</pubDate>
      <link>https://forem.com/adzubla/db2-backuprestore-schema-f4e</link>
      <guid>https://forem.com/adzubla/db2-backuprestore-schema-f4e</guid>
      <description>&lt;h1&gt;
  
  
  Creating the backup
&lt;/h1&gt;

&lt;p&gt;Exporting DDL from EXAMPLE schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db2look -d MYDB -z EXAMPLE -e -o EXAMPLE.sql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Exporting data from schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db2move MYDB export -sn EXAMPLE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;db2move&lt;/code&gt; command will create a lot of files, incluing &lt;code&gt;db2move.lst&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It contains internal tables like EXPLAIN_* and ADVISE_*. If you don't need them just delete de corresponding lines from &lt;code&gt;db2move.lst&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Restoring backup
&lt;/h1&gt;

&lt;p&gt;Creating objects:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db2 -t -f EXAMPLE.sql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restoring data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db2move MYDB import

db2move MYDB import -io insert_update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>db2</category>
      <category>backup</category>
    </item>
    <item>
      <title>Using MTLS</title>
      <dc:creator>Eduardo Issao Ito</dc:creator>
      <pubDate>Tue, 12 Apr 2022 17:02:35 +0000</pubDate>
      <link>https://forem.com/adzubla/using-mtls-5711</link>
      <guid>https://forem.com/adzubla/using-mtls-5711</guid>
      <description>&lt;h1&gt;
  
  
  Using MTLS
&lt;/h1&gt;

&lt;p&gt;It is common for the server to be authenticated by a certificate, but in this case the client also has one. With MTLS the server can be sure who the client is.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;MTLS means "mutual TLS authentication" or "two-way TLS authentication".&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The scenario is: client (Amy) accessing server (Bob) using MTLS.&lt;/p&gt;

&lt;p&gt;The diagram below shows how the server and client certificates are created.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzcgntbkn3cg4ste6nj2o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzcgntbkn3cg4ste6nj2o.png" alt="Image creating certificates"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The CA (certification authority) is a third party responsible for signing the certificates with a trusted root certificate. But it is common to use a CA that belongs to one of the two parties (Amy ou Bob).&lt;/p&gt;

&lt;p&gt;It is also possible that Amy uses one CA and Bob chooses another (it will be explained later).&lt;/p&gt;

&lt;p&gt;Note that the procedure for creating the server certificate is the same as for the client certificate. The only difference is in the common name used in the certificate subject:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The CN of the server must be the name that the Amy uses to access Bob.&lt;/li&gt;
&lt;li&gt;The CN of the client can be anything, although the server can use it to do some additional validation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1. [CA] creation of a self-signed root CA X.509 certificate
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openssl req &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-new&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-x509&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-nodes&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-days&lt;/span&gt; 365 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-subj&lt;/span&gt; &lt;span class="s1"&gt;'/CN=my-ca'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-keyout&lt;/span&gt; ca.key &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-out&lt;/span&gt; ca.crt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. [Bob, server side] create the server’s key
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openssl genrsa &lt;span class="nt"&gt;-out&lt;/span&gt; bob_server.key 2048
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. [Bob, server side] request the server’s certificate
&lt;/h2&gt;

&lt;p&gt;The Common Name in the subject should reflect the server name that will be used by clients, like &lt;code&gt;srv.bob.com&lt;/code&gt;. For&lt;br&gt;
testing purposes, we will simply assume &lt;code&gt;localhost&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openssl req &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-new&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-key&lt;/span&gt; bob_server.key &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-subj&lt;/span&gt; &lt;span class="s1"&gt;'/CN=localhost'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-out&lt;/span&gt; bob_server.csr
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Certificate Signing Request (csr file) generated in this step must be sent to the CA to proceed with the creation of&lt;br&gt;
the certificate.&lt;/p&gt;
&lt;h2&gt;
  
  
  4. [CA, on behalf of Bob] Using the CSR, the CA creates the signed server certificate:
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openssl x509 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-req&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-in&lt;/span&gt; bob_server.csr &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-CA&lt;/span&gt; ca.crt &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-CAkey&lt;/span&gt; ca.key &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-CAcreateserial&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-days&lt;/span&gt; 365 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-out&lt;/span&gt; bob_server.crt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The certificate (crt file) is sent to Bob.&lt;/p&gt;
&lt;h2&gt;
  
  
  5. [Amy, client side] create the clients’s key
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openssl genrsa &lt;span class="nt"&gt;-out&lt;/span&gt; amy_client.key 2048
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  6. [Amy, client side] request the server’s certificate
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openssl req &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-new&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-key&lt;/span&gt; amy_client.key &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-subj&lt;/span&gt; &lt;span class="s1"&gt;'/CN=amy-client'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-out&lt;/span&gt; amy_client.csr
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The Certificate Signing Request (csr file) generated in this step must be sent to the CA to proceed with the creation of&lt;br&gt;
the certificate.&lt;/p&gt;
&lt;h2&gt;
  
  
  7. [CA, on behalf of Amy] Using the CSR, the CA creates the signed client certificate:
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openssl x509 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-req&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-in&lt;/span&gt; amy_client.csr &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-CA&lt;/span&gt; ca.crt &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-CAkey&lt;/span&gt; ca.key &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-CAcreateserial&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-days&lt;/span&gt; 365 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-out&lt;/span&gt; amy_client.crt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The certificate (crt file) is sent to Amy.&lt;/p&gt;
&lt;h1&gt;
  
  
  Test
&lt;/h1&gt;
&lt;h2&gt;
  
  
  Start Bob's server:
&lt;/h2&gt;

&lt;p&gt;Start node application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node app_bob.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to allow only clients with the more secure TLS v1.3:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node &lt;span class="nt"&gt;--tls-min-v1&lt;/span&gt;.3 app_bob.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Execute Amy's client:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cacert&lt;/span&gt; ca.crt &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--key&lt;/span&gt; amy_client.key &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cert&lt;/span&gt; amy_client.crt &lt;span class="se"&gt;\&lt;/span&gt;
  https://localhost:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Using distinct CAs
&lt;/h1&gt;

&lt;p&gt;If Amy and Bob are using distinct CAs, they need to know each other root certificates.&lt;/p&gt;

&lt;p&gt;Assume that Amy's and Bob's CAs have certificates &lt;code&gt;amy_ca.crt&lt;/code&gt; and &lt;code&gt;bob_ca.crt&lt;/code&gt;, respectively.&lt;/p&gt;

&lt;p&gt;So, Bob must load the certificate used by Amy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;options&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;ca:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;fs.readFileSync('amy_ca.crt')&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And Amy's client need to know the certificate used by Bob:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cacert&lt;/span&gt; bob_ca.crt &lt;span class="se"&gt;\&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F52au97pd6atfklo5ffp9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F52au97pd6atfklo5ffp9.png" alt="Image creating certificates"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These are complete instructions to create this scenario:&lt;/p&gt;

&lt;p&gt;Bob (server side):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openssl req &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-new&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-x509&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-nodes&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-days&lt;/span&gt; 365 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-subj&lt;/span&gt; &lt;span class="s1"&gt;'/CN=bob-ca'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-keyout&lt;/span&gt; bob_ca.key &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-out&lt;/span&gt; bob_ca.crt

openssl genrsa &lt;span class="nt"&gt;-out&lt;/span&gt; bob_server.key 2048

openssl req &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-new&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-key&lt;/span&gt; bob_server.key &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-subj&lt;/span&gt; &lt;span class="s1"&gt;'/CN=localhost'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-out&lt;/span&gt; bob_server.csr

openssl x509 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-req&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-in&lt;/span&gt; bob_server.csr &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-CA&lt;/span&gt; bob_ca.crt &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-CAkey&lt;/span&gt; bob_ca.key &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-CAcreateserial&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-days&lt;/span&gt; 365 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-out&lt;/span&gt; bob_server.crt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Amy (client side):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openssl req &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-new&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-x509&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-nodes&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-days&lt;/span&gt; 365 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-subj&lt;/span&gt; &lt;span class="s1"&gt;'/CN=amy-ca'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-keyout&lt;/span&gt; amy_ca.key &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-out&lt;/span&gt; amy_ca.crt

openssl genrsa &lt;span class="nt"&gt;-out&lt;/span&gt; amy_client.key 2048

openssl req &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-new&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-key&lt;/span&gt; amy_client.key &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-subj&lt;/span&gt; &lt;span class="s1"&gt;'/CN=amy-client'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-out&lt;/span&gt; amy_client.csr

openssl x509 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-req&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-in&lt;/span&gt; amy_client.csr &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-CA&lt;/span&gt; amy_ca.crt &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-CAkey&lt;/span&gt; amy_ca.key &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-CAcreateserial&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-days&lt;/span&gt; 365 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-out&lt;/span&gt; amy_client.crt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Reference
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/adzubla/mtls-test" rel="noopener noreferrer"&gt;https://github.com/adzubla/mtls-test&lt;/a&gt;&lt;/p&gt;

</description>
      <category>mtls</category>
      <category>ssl</category>
      <category>https</category>
    </item>
    <item>
      <title>Convert OpenAPI spec to JSON Schema</title>
      <dc:creator>Eduardo Issao Ito</dc:creator>
      <pubDate>Tue, 09 Feb 2021 14:05:13 +0000</pubDate>
      <link>https://forem.com/adzubla/convert-openapi-spec-to-json-schema-29bc</link>
      <guid>https://forem.com/adzubla/convert-openapi-spec-to-json-schema-29bc</guid>
      <description>&lt;p&gt;I've created a Groovy script to convert from "OpenAPI" specification (aka Swagger file) to "JSON Schema".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/adzubla/schema-convert"&gt;https://github.com/adzubla/schema-convert&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;groovy SchemaConvert.groovy openapi-spec.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can add the &lt;code&gt;-m&lt;/code&gt; option to generate a schema compatible with MongoDB.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;groovy SchemaConvert.groovy openapi-spec.yaml &lt;span class="nt"&gt;-m&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Sample execution
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;groovy SchemaConvert.groovy petstore.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Input file &lt;code&gt;petstore.yaml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;openapi&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.0.0"&lt;/span&gt;
&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1.0.0&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Swagger Petstore&lt;/span&gt;
  &lt;span class="na"&gt;license&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MIT&lt;/span&gt;
&lt;span class="na"&gt;servers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://petstore.swagger.io/v1&lt;/span&gt;
&lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="s"&gt;/pets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;List all pets&lt;/span&gt;
      &lt;span class="na"&gt;operationId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;listPets&lt;/span&gt;
      &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;pets&lt;/span&gt;
      &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;limit&lt;/span&gt;
          &lt;span class="na"&gt;in&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;query&lt;/span&gt;
          &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;How many items to return at one time (max 100)&lt;/span&gt;
          &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
          &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;integer&lt;/span&gt;
            &lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;int32&lt;/span&gt;
      &lt;span class="na"&gt;responses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;200'&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;A paged array of pets&lt;/span&gt;
          &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;x-next&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;A link to the next page of responses&lt;/span&gt;
              &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
          &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;    
              &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="s"&gt;$ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#/components/schemas/Pets"&lt;/span&gt;
        &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unexpected error&lt;/span&gt;
          &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="s"&gt;$ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#/components/schemas/Error"&lt;/span&gt;
    &lt;span class="na"&gt;post&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Create a pet&lt;/span&gt;
      &lt;span class="na"&gt;operationId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;createPets&lt;/span&gt;
      &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;pets&lt;/span&gt;
      &lt;span class="na"&gt;responses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;201'&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Null response&lt;/span&gt;
        &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unexpected error&lt;/span&gt;
          &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="s"&gt;$ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#/components/schemas/Error"&lt;/span&gt;
  &lt;span class="s"&gt;/pets/{petId}&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Info for a specific pet&lt;/span&gt;
      &lt;span class="na"&gt;operationId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;showPetById&lt;/span&gt;
      &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;pets&lt;/span&gt;
      &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;petId&lt;/span&gt;
          &lt;span class="na"&gt;in&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;path&lt;/span&gt;
          &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
          &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;The id of the pet to retrieve&lt;/span&gt;
          &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
      &lt;span class="na"&gt;responses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;200'&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Expected response to a valid request&lt;/span&gt;
          &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="s"&gt;$ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#/components/schemas/Pets"&lt;/span&gt;
        &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unexpected error&lt;/span&gt;
          &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="s"&gt;$ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#/components/schemas/Error"&lt;/span&gt;
&lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;schemas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Pets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;array&lt;/span&gt;
      &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="s"&gt;$ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#/components/schemas/Pet"&lt;/span&gt;
    &lt;span class="na"&gt;Pet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;id&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;name&lt;/span&gt;
      &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;integer&lt;/span&gt;
          &lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;int64&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
        &lt;span class="na"&gt;tag&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
    &lt;span class="na"&gt;Error&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;code&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;message&lt;/span&gt;
      &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;integer&lt;/span&gt;
          &lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;int32&lt;/span&gt;
        &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output file &lt;code&gt;petstore.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Json validation with OpenAPI Schema</title>
      <dc:creator>Eduardo Issao Ito</dc:creator>
      <pubDate>Tue, 09 Feb 2021 13:55:26 +0000</pubDate>
      <link>https://forem.com/adzubla/json-validation-with-openapi-schema-4cda</link>
      <guid>https://forem.com/adzubla/json-validation-with-openapi-schema-4cda</guid>
      <description>&lt;p&gt;How to validate a json file against a Schema that is defined in an OpenAPI definition?&lt;/p&gt;

&lt;p&gt;Using the open source library &lt;code&gt;openapi4j&lt;/code&gt;!&lt;/p&gt;

&lt;p&gt;Add the dependencies in your pom.xml file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;        &lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.openapi4j&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;openapi-parser&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.0.5&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;

        &lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.openapi4j&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;openapi-schema-validator&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.0.5&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Load the OpenAPI definition (&lt;code&gt;petstore.yaml&lt;/code&gt;) and the json file (&lt;code&gt;pets.json&lt;/code&gt;) to validate against the &lt;code&gt;Pets&lt;/code&gt; schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;        &lt;span class="no"&gt;URL&lt;/span&gt; &lt;span class="n"&gt;specURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="no"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"file:src/main/resources/petstore.yaml"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="no"&gt;URL&lt;/span&gt; &lt;span class="n"&gt;contentURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="no"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"file:src/main/resources/pets.json"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;schemaName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Pets"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="nc"&gt;OpenApi3&lt;/span&gt; &lt;span class="n"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OpenApi3Parser&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;parse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;specURL&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;JsonNode&lt;/span&gt; &lt;span class="n"&gt;contentNode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TreeUtil&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;load&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;contentURL&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;Schema&lt;/span&gt; &lt;span class="n"&gt;schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getComponents&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getSchema&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;schemaName&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;JsonNode&lt;/span&gt; &lt;span class="n"&gt;schemaNode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;schema&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toNode&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="nc"&gt;SchemaValidator&lt;/span&gt; &lt;span class="n"&gt;schemaValidator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SchemaValidator&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ValidationContext&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getContext&lt;/span&gt;&lt;span class="o"&gt;()),&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;schemaNode&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;ValidationData&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;validation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ValidationData&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
        &lt;span class="n"&gt;schemaValidator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;validate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;contentNode&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;validation&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;validation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isValid&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ok"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;validation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;results&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If there is any inconsistency, the &lt;code&gt;ValidationData&lt;/code&gt; object will have a list of all errors found.&lt;/p&gt;

</description>
      <category>openapi4j</category>
      <category>openapi</category>
      <category>schema</category>
    </item>
    <item>
      <title>SFTP server in Ubuntu</title>
      <dc:creator>Eduardo Issao Ito</dc:creator>
      <pubDate>Mon, 08 Feb 2021 16:56:32 +0000</pubDate>
      <link>https://forem.com/adzubla/sftp-server-in-ubuntu-4db4</link>
      <guid>https://forem.com/adzubla/sftp-server-in-ubuntu-4db4</guid>
      <description>&lt;p&gt;How to setup a basic SFTP server in Ubuntu.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;No login&lt;/li&gt;
&lt;li&gt;Read and write permissions&lt;/li&gt;
&lt;li&gt;Access only to a base directory&lt;/li&gt;
&lt;li&gt;Default directory should be the base directory&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Instalation
&lt;/h2&gt;

&lt;h5&gt;
  
  
  Install the sftp server package
&lt;/h5&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt-get install openssh-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h5&gt;
  
  
  Create sftp group and user
&lt;/h5&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo groupadd sftpgroup
sudo useradd myuser -m -G sftpgroup -s /usr/sbin/nologin
sudo passwd myuser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h5&gt;
  
  
  Prepare base sftp directory
&lt;/h5&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo chown root:root /home/myuser
sudo mkdir /home/myuser/data
sudo chown myuser:sftpgroup /home/myuser/data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h5&gt;
  
  
  Configure sftp server
&lt;/h5&gt;

&lt;p&gt;Edit the file &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Comment the following line:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#Subsystem sftp /usr/lib/openssh/sftp-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Add the folowing lines at the end of the file:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Subsystem sftp internal-sftp
Match group sftpgroup
ChrootDirectory %h
X11Forwarding no
AllowTcpForwarding no
ForceCommand internal-sftp -d /data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Restart the server&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo service ssh restart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Test
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ sftp myuser@localhost
myuser@localhost's password:
Connected to localhost.
sftp&amp;gt; pwd
Remote working directory: /data
sftp&amp;gt; put test.txt
Uploading test.txt to /data/test.txt
test.txt                                                                              100%    0     0.0KB/s   00:00
sftp&amp;gt; ls
test.txt
sftp&amp;gt; quit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>sftp</category>
      <category>sftpserver</category>
    </item>
  </channel>
</rss>
