728x90

기본적으로 조져지던 Swagger는 Springfox 에서 조져지는데 이 친구들은 3.x.x 대로 올라오면서 사실상 업데이트가 제대로 맞춰지지 않았기 때문에 엄청나게 거시기 한 점이 있다.

 

 따라서 OpenAPI의 SpringDoc 를 조져주는 게 좋은데,  이 경우에도 버전에 따라서 양상이 좀 다르게 바뀐다

 

3 버전대 이전 버전에서 Spring Doc 조지기

implementation("org.springdoc:springdoc-openapi-ui:1.6.11")

 

3.2.2 버전의 경우 아래와 같이 dedencies 를 조져준다

implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2'

 

잘 보면 의존성에 따라서 Library 가 변한 것을 알 수 있는데, 결과적으로 버전에 따른 Library 를 안맞춰주면 

Whitelabel Error Page를 감상할 수 있다.

대충 이렇게 생긴 친구인데 의존성을 안맞춰주면 2024년도에도 이렇게 똑같이 발생한다는 말이다.

 

또한 괜히 Library 는 많으면 많을 수록 좋다는 생각으로 2가지 친구를 동시에 추가시켜 줬다가는 다음과 같은 빨간맛을 볼 수 있다.

 

after Using .apis(RequestHandlerSelectors.basePackage("com.szs.columbus.controller")) // Replace with your controller package, I'm in error like this
Unable to infer base url. This is common when using dynamic servlet registration or when the API is behind an API Gateway. The base url is the root of where all the swagger resources are served. For e.g. if the api is available at http://example.org/api/v2/api-docs then the base url is http://example.org/api/. Please enter the location manually:

 

그리고 추가적으로 종종 localhost 기반에서 들어가서 접속해보면 박스가 하나 뜨면서 

너새끼의 basePackage 가 잘못되었으니 수동으로 한번 꼬라박아줄래? 라고 계속 물어본다

 


번외. Springfox 너새끼는 어디까지 가능한가

추가적으로 Springfox 3.0.0에서는 Spring Boot 2.5와 2.6 에서 사용되는 것과 별개로 약간의 변화가 생기는데.

2. Remove Explicit @EnableSwagger2 Annotation

Springfox 3.0.0 and later versions with Spring Boot starters do not require the @EnableSwagger2 annotation. You can remove this annotation from your configuration class.

 

Annotation 하나를 제거해준다는 특징이 있다.

 

결론 = 그냥 어지간하면 이제는 OpenAPI 의 SpringDoc 이 답이다

 


추가적으로 application.properties 에서 path 기반하에 있는걸 다 박아주는 것도 설정할  수 있는데

 

In application.properties 

# Swagger Base
springdoc.packages-to-scan=com.szs.columbus.controller

 

이런식으로 Controller Package 하부를 죄다 박아버릴 수 있다. (이건 당연히 예전에 Springfox 에서도 지원되던 것이다.)

 

 

참조하면 좋은 글

https://sjh9708.tistory.com/169

 

[Spring Boot] Swagger API Docs 작성하기 (SpringDoc, SpringBoot 3 버전)

이전에 Spring Boot 프로젝트에 Swagger를 연동해 본 적이 있었다. 최근 Spring Boot의 지원 버전이 3점대로 올라감과 동시에, 2점대에서 Swagger 사용 목적으로 많이 사용되는 SpringFox가 안타깝게도 제대로

sjh9708.tistory.com

https://colabear754.tistory.com/99

 

[Spring Boot] Springdoc 라이브러리를 통한 Swagger 적용

목차 기본 환경 IntelliJ Ultimate 2022.3 Spring Boot 2.7.7 Kotlin 1.7.21(JDK 11) Springdoc Openapi UI 1.6.11 Springdoc은 무엇인가? 이전에 Spring Boot 프로젝트에 Swagger UI를 적용하는 포스트를 작성한 적이 있다. 해당 포

colabear754.tistory.com

 

728x90

Swagger 를 사용하여 API가 실행되도록 하고 구현한 상태에서 모듈에 관련된 문제가 발생했다.

 

bootRun으로 Gradle 을 돌리다가 아래와 같이 뻗어버린 사태였는데, 해답은 간단하게 이미 적혀있듯

classgraph 를 조져주면된다

 

 

***************************
APPLICATION FAILED TO START
***************************

Description:

An attempt was made to call a method that does not exist. The attempt was made from the following location:

    org.webjars.WebJarAssetLocator.scanForWebJars(WebJarAssetLocator.java:188)

The following method did not exist:

    'io.github.classgraph.ClassGraph io.github.classgraph.ClassGraph.acceptPaths(java.lang.String[])'

The calling method's class, org.webjars.WebJarAssetLocator, was loaded from the following location:

    jar:file:/C:/Users/35mwl/.gradle/caches/modules-2/files-2.1/org.webjars/webjars-locator-core/0.55/d9c819930f44c89af1a6a8af2db6364926f6be69/webjars-locator-core-0.55.jar!/org/webjars/WebJarAssetLocator.class

The called method's class, io.github.classgraph.ClassGraph, is available from the following locations:

    jar:file:/C:/Users/35mwl/.gradle/caches/modules-2/files-2.1/io.github.classgraph/classgraph/4.8.69/6bd8c9033563e162b5c12de12b139724dbf71f48/classgraph-4.8.69.jar!/io/github/classgraph/ClassGraph.class

The called method's class hierarchy was loaded from the following locations:

    io.github.classgraph.ClassGraph: file:/C:/Users/35mwl/.gradle/caches/modules-2/files-2.1/io.github.classgraph/classgraph/4.8.69/6bd8c9033563e162b5c12de12b139724dbf71f48/classgraph-4.8.69.jar


Action:

Correct the classpath of your application so that it contains compatible versions of the classes org.webjars.WebJarAssetLocator and io.github.classgraph.ClassGraph


> Task :bootRun FAILED

Execution failed for task ':bootRun'.
> Process 'command 'C:\Users\35mwl\.jdks\corretto-18.0.2\bin\java.exe'' finished with non-zero exit value 1

 

build.gradle 에 다음과 같이 모듈 삽입을 해주고 Gradle sync 까지 마쳐준다

dependencies {
    // ... other dependencies ...
    implementation 'org.webjars:webjars-locator-core:0.46' // Update to a compatible version
    implementation 'io.github.classgraph:classgraph:4.8.69' // Update to a compatible version
}

 

728x90

The HTTP 401 response code indicates an "Unauthorized" error. This typically means that the request requires user authentication which has not been provided or which has failed. Here are some common reasons and solutions for this issue in a Spring Boot application:

1. Spring Security Configuration

If your Spring Boot application is using Spring Security, it might be configured to require authentication for accessing the API endpoints. This is a common scenario when Spring Security is included in the project dependencies.

Solutions:

  • Provide Authentication Credentials: If your API requires authentication, you need to provide the correct credentials in your request header. In Postman, you can do this in the Authorization tab, selecting the type of authentication your API uses (like Basic Auth, Bearer Token, etc.) and entering the required credentials.
  • Adjust Security Configuration: If the /users endpoint should be publicly accessible without authentication, you'll need to adjust your Spring Security configuration to permit requests to this endpoint. Here’s an example of how you might configure this in your WebSecurityConfigurerAdapter:
@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        // ... other configurations ...
        .authorizeRequests()
        .antMatchers("/users").permitAll() // Permit requests to /users endpoint
        .anyRequest().authenticated()
        // ... other configurations ...
}

 

2. CSRF Protection

Spring Security's CSRF (Cross-Site Request Forgery) protection is enabled by default. If you are making a POST request to your Spring Boot application from Postman or another REST client, CSRF protection might block it.

Solutions:

  • Include CSRF Token: If CSRF protection is necessary (usually for browser-based applications), include the CSRF token in your request.
  • Disable CSRF Protection for API Endpoints: If you're building a stateless REST API (especially one used by non-browser clients), you might consider disabling CSRF protection for those endpoints:
@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        // ... other configurations ...
        .csrf().disable() // Disable CSRF protection
        // ... other configurations ...
}

3. CORS Configuration

While the 401 error isn't directly related to CORS (Cross-Origin Resource Sharing), incorrect CORS settings can sometimes manifest as authentication issues, especially if you're calling the API from a different domain.

Solution:

  • Configure CORS Settings: Ensure that your Spring Boot application has the correct CORS settings if your API is being accessed from a different domain.

4. Check Server Logs

Finally, check your server logs for any additional information or error messages related to the failed request. The logs can provide more specific details about why the request was unauthorized.

By addressing these areas, you should be able to resolve the 401 error and successfully make POST requests to your /users endpoint.

 
 
 
728x90

1. Reserved Keyword 

 GenerationTarget encountered exception accepting command : Error executing DDL "create table evaluation (id bigint generated by default as identity, comment varchar(255), content_id bigint, like boolean, unlike boolean, user_id bigint, primary key (id))" via JDBC [Syntax error in SQL statement "create table evaluation (id bigint generated by default as identity, comment varchar(255), content_id bigint, [*]like boolean, unlike boolean, user_id bigint, primary key (id))"; expected "identifier";]

 

위에서 나온 부분은 Reserved Keyword (예약어) 에 대한 사용이다.

 

 JPA  를 사용할 때에 JPA는 형상변환을 거쳐 SQL 문법 (Diarect)로 변환되게 되는데, 코드상에서 보면 당연히 '좋아요' 를 like로 지정할 수 있겠지만 이러한 부분은 SQL 문법에서의 like 와 문제를 일으키게 된다.

 

문제가 되는 코드를 살펴보자

 

package com.webtoon.webtoonservice.model;

import jakarta.persistence.*;

@Entity
public class Evaluation {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private Long userId;
    private Long contentId;
    private Boolean like;
    private Boolean unlike;
    private String comment; // Ensure validation to disallow special characters
}

 

이 부분에서 해당하는 부분을 고치려면 like를 likes 로 고치거나 이스케이핑을 하면 된다.

 

@Entity
@Table(name = "evaluation")
public class Evaluation {
    // other fields...

    @Column(name = "`like`")
    private Boolean like;
    private Boolean unlike;

    // getters and setters...
}

 


2. Reserved Keyword

GenerationTarget encountered exception accepting command : Error executing DDL "create table user (id bigint generated by default as identity, gender varchar(255), register_date timestamp(6), type varchar(255), user_email varchar(255), user_name varchar(255), primary key (id))" via JDBC [Syntax error in SQL statement "create table [*]user (id bigint generated by default as identity, gender varchar(255), register_date timestamp(6), type varchar(255), user_email varchar(255), user_name varchar(255), primary key (id))"; expected "identifier";]

 

가장 눈치채기 어려운 것 중 하나인 user 에 대한 부분이다. 변환하는 과정 도중 Directs 중에서 user 라는 부분은 이미 잡혀있는 user table 을 지칭하여 문제를 일으킬 수 있기 마련인데 이러한 부분 때문에 문제가 발생한다.

 

package com.webtoon.webtoonservice.model;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;


import jakarta.persistence.*;
import java.util.Date;



@Entity
@Table(name = "`user`") // use backticks to escape
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String userName;
    private String userEmail;
    private String gender; // Consider using an enum here
    private String type;   // Consider using an enum here
    private Date registerDate;
}

 

마찬가지로 이스케이핑을 하여 처리할 수 있다.

'Java > Spring Boot JPA' 카테고리의 다른 글

[Trouble Shooting] Open API  (1) 2024.02.01
HTTP 401 response code  (0) 2024.01.12
[Shop] 세션 끊김 문제 완전 해결  (0) 2023.09.21
[Shop] Session Failure Problem  (0) 2023.09.16
[sync] Complete Session Sync issue  (0) 2023.09.01

+ Recent posts