반응형

간만에 aop사용하다가 별것도 아닌데 삽질을 좀 했다

-> AOP 적용중 다음과 같은 에러 발생

Caused by: java.lang.IllegalArgumentException: Pointcut is not well-formed: expecting ')' at character position 0
@annotation(im.toss.server.tuba.messenger.system.ElasticSearchDocumentSync
^

-> 에러 발생 Poinctcut 코드

 

-> 문제 해결 > annotation 괄호가 제대로 안닫혀있었음...😅

반응형
반응형

springboot버전에 맞지 않는 spring cloud dependency를 추가하게 되면 다음과 같은 에러메세지를 만난다.

org.springframework.beans.factory.BeanCreationException: Error creating bean with name
	'configurationPropertiesBeans' defined in class path resource 
    [org/springframework/cloud/autoconfigure/ConfigurationPropertiesRebinderAutoConfiguration.class]:
    Bean instantiation via factory method failed; nested exception is org.springframework.beans
	.BeanInstantiationException: Failed to instantiate [org.springframework.cloud.conte
    xt.properties.ConfigurationPropertiesBeans]: Factory method 'configurationPropertiesBeans' threw exception; nested exception is java.lang.NoClassDefFoundError: org/springframework/boot/context/properties/ConfigurationBeanFactoryMetadata
	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(Constr
    uctorResolver.java:658) ~[spring-beans-5.3.12.jar:5.3.12]

.
.
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate 
	[org.springframework.cloud.context.properties.ConfigurationPropertiesBeans]: 
    Factory method 'configurationPropertiesBeans' threw exception; 
    nested exception is java.lang.NoClassDefFoundError
Caused by: java.lang.NoClassDefFoundError: org/springframework/boot/context/properties/ConfigurationBeanFactoryMetadata

 

따라서 아래의 표와같이 springboot version에 맞는 springcloud version을 맞춰주도록 하자~!

Release TrainBoot Version

2020.0.x aka Ilford 2.4.x, 2.5.x (Starting with 2020.0.3)
Hoxton 2.2.x, 2.3.x (Starting with SR5)
Greenwich 2.1.x
Finchley 2.0.x
Edgware 1.5.x
Dalston 1.5.x

 

반응형
반응형

스프링부트 사용하면서부터 RestTemplate을 많이 사용하여 API개발을 해왔었다.

하지만 최근에 알게된 사실은 블로킹 API로 리액티브 기반의 애플리케이션에서의 성능을 떨어트리는 원인이 될 수 있다는 걸 알게 되었다. 또한 Spring5.0버전부터는 RestTemplate은 유지모드로 변경되고 향우 deprecated될 예정이라고 한다.

따라서 대안으로 Spring에서는 WebClient사용을 권고하고 있으며 다음과 같은 장점이 있다.

  • Non-blocking I/O
  • Reactive Streams back pressure
  • High concurrency with fewer hardware resources
  • Functional-style, fluent API that takes advantage of Java 8 lambdas
  • Synchronous and asynchronous interactions
  • Streaming up to or streaming down from a server

WebClient에 대한 자세한 사용법에 대해서 알고 싶다면 아래의 블로그 글을 참고하자.

medium.com/@odysseymoon/spring-webclient-%EC%82%AC%EC%9A%A9%EB%B2%95-5f92d295edc0

 

Spring WebClient 사용법

Spring 어플리케이션에서 HTTP 요청을 할 땐 주로 RestTemplate 을 사용했었습니다. 하지만 Spring 5.0 버전부터는 RestTemplate 은 유지 모드로 변경되고 향후 deprecated 될 예정입니다.

medium.com

 

스프링공식문서

www.baeldung.com/spring-webclient-resttemplate

 

Spring WebClient vs. RestTemplate | Baeldung

Learn how to make server-side HTTP calls using WebClient and RestTemplate.

www.baeldung.com

 

반응형
반응형

최근 읽고 있는 '자바 최적화'라는 책을 보다가 몰랐었던 내용이 있어 기록할겸 남겨본다. 

자바7 이전 리소스 사용후 닫는 것은 온전히 개발자의 몫

    public void readFirstLineOld(File file) throws IOException {
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader(file));
            String FirstLine = reader.readLine();
        } finally {
            if (reader != null) {
                reader.close();
            }
        }
    }

 

자바7 부터 언어 자체에 추가된 try-with-resources 생성자를 이용하면 try키워드 다음의 괄호 안에 리소스(AutoCloseable 인터페이스를 구현한 객체만 가능)를 지정해서 생성할 수 있다. 이로써 try 블록이 끝나는 지점에 개발자가 close() 메서드 호출을 깜빡 잊고 빠뜨려도 자동으로 호출된다. close() 메서드는 방금 전 예제와 똑같이 호출되고 비지니스 로직의 예외 발생 여부와 상관없이 무조건 실행된다.

    public void readFirstLineOld(File file) throws IOException {
        try( BufferedReader reader = new BufferedReader(new FileReader(file))) {
            String FirstLine = reader.readLine();
        }
    }

코드가 훨씬 심플해졌다. 하지만 try-with-resources 생성자 사용시 자동으로 close() 를 호출해주는 것을 몰랐다면 finally 코드를 생성해 그 안에서 또 close를 호출하려고 하였을거다...

위의 예에서는 catch(IOException exception) {} 과 같이 별도로 에러처리를 안해주고 그냥 상위로 exception을 그냥 던져버리는데 사실 좋지 않다. 항상 에러 발생시 catch 내부에서 잡고 로깅해주고 처리해주는 것이 좋다.

이번 포스팅을 하며 느낀점은 기본에 좀 더 충실한 공부가 필요할 것 같다.

 

반응형
반응형

자바 스트림 Skip 사용시 java.lang.IllegalArgumentException: -number 형태의 에러가 나는 이유는

skip 메서드의 인자로 0보다 작은 값이 들어 갔기 때문이다.

따라서 어떤 수치를 계산해서 skip에 인자를 전달하고 있다면 해당 값이 0보다 작지 않은 지 확인해보자.

skip 내부 로직

반응형
반응형

Upper of POI 3.x Version, cell fill color is set as follows

setFillBackgroundColor (x)

setFillForegroundColor (0)

자바 엑셀 파일 배경색이 계속 검정색이거나 안바뀔 때는 setFillForeGroundColor대신 setFillForeGroundColor를 사용하자. POI 3.x윗 버전부터는 ForegroundColor를 써야 바뀌는듯....

        CellStyle styleBlueColor = workbook.createCellStyle();
        styleBlueColor.setFillForegroundColor(IndexedColors.CORNFLOWER_BLUE.getIndex());
        styleBlueColor.setFillPattern(FillPatternType.SOLID_FOREGROUND);

        cell = row.createCell(0);
        cell.setCellStyle(styleLimeColor);
        cell.setCellValue("인보이스번호");
반응형
반응형

자바 어플리케이션을 개발하다 보면 외부 프로세스를 실행해야 할 경우가 있다.

예를 들어 자바 어플리케이션 내에서 서버의 특정 스크립트를 실행한다거나 다른 시스템 (spark, hadoop etc)에 명령을 내리는 경우다.

이번에 포스팅 할 내용은 JAVA process exec()명령을 실행하고 process.waitFor()를 실행함으로써 시스템이 행이 걸려 한참을 헤맨 내용이다.......정확히는 자바 어플리케이션 내부에서 Spark 어플리케이션을 실행하고 waitFor로 작업이 마무리 되었을 때 그 다음 작업을 진행시키는 배치가 맛이 가버린 내용이다.

자바내에서 특정 입력값을 사용자로 부터 받아 스파크(SPARK)의 특정 작업을 여러번 호출시키도록 설계되어 있다. admin시스템으로써 외부 부서에서 보통 3개의 입력값만 사용한다고 하셨었고 당연히 기능 개발후 테스트까지 마친 상태였다.

하지만 문제는 사용자가 5개의 입력값을 입력함으로써 시작되었다.....처음에는 Spark작업을 의심했었다. 다량의 Input값으로 메모리문제가 발생해 정상적인 아웃풋을 자바 어플리케이션에 전달하지 못하여 배치가 hang에 걸린 줄 알았었으나....그 문제는 아니였다.

[ 문제가 발생한 기존 코드 ] 

Process process = Runtime.getRuntime().exec(command);
process.waitFor();

보통 이렇게만 해도 큰 문제가 되지 않는다. 왜냐하면 보통 Command라고 해봤자 정말 단순한 명령어(grep, kill과 같은 단순한 리눅스 명령어)일 확률이 높기 때문이다.

하지만 이번 경우에는 달랐다.

문제는 명령어의 입력값이 커지면서 스파크(Spark) 작업이 여러번 돌게 되었고 작업이 끝나는 동안 outputstream을 한 번도 읽어주지 않음으로써 해당 버퍼가 꽉 차버리면서 정상적인 결과값을 읽지 읽어들이지 못하게 되면서 waitFor가 계속해서 끝나지 않는 상태가 되어 hang이 걸리게 되는 것이다.

 

[ 문제를 해결 코드 ] 

가장 간단하게는 process의 outputstrem을 받아 close해주는 방식이다.

process.getOutputStream().close();

행에 걸린 경우는 별도의 에러코드도 내뱉지 않게 된다. 문제 발생시 에러에 대한 내용 파악이 필요하다면  process.getErrorStream() 을 받아 처리하는 부분의 구현이 필요하다.

관련해서 java.lang.Process 클래스의 API 문서에 다음과 같이 나와있다.

Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, and even deadlock.

간단히 말해 표준입력과 출력에 대한 버퍼 사이즈가 제한이 되어 있고, subprocess의 input stream과 또는 output stream을 즉시 읽지 못한다면 subprocess가 block되거나 심지어 deadlock에 빠질 수 있다는 것이다.

이렇게 나는 이런 버퍼관련 이슈와 관련 신경쓰지 않고 싶을 경우에는 Apache Commons Exec를 쓰면 된다.

좀 더 자세한 내용이 궁금하다면 아래의 참고문헌을 참고 바란다.

[ 참고 문헌 ]

https://d2.naver.com/helloworld/1113548

https://pasudo123.tistory.com/250

https://stackoverflow.com/questions/5483830/process-waitfor-never-returns

반응형
반응형

JPA사용시 native query로 @Param 애노테이션을 통해 Model을 사용하는 방법과 발생할 수 있는 에러에 대해서 알아보자.

작업중 다음과 같은 에러가 발생

[ 작업 코드 ] 

문제가 된 부분

[ 에러 1 ]

org.hibernate.QueryException: Named parameter not bound : range.leftBottomLatitude
org.hibernate.query.internal.QueryParameterBindingsImpl.verifyParametersBound(QueryParameterBindingsImpl.java:210) ~[hibernate-core-5.3.10.Final.jar:5.3.10.Final]
.
.

[ 에러 2]

org.hibernate.QueryException: Named parameter not bound : __$synthetic$__1and
.
.

[ 해결책 ]

마지막 줄 이외의 쿼리문 끝에 한 칸을 띄워준다!!!

쿼리문 끝에 한 칸을 띄워준다!!!

 

포스팅 마무리하도록 하겠습니다.

반응형
반응형

스프링부트에서 JavamailSender사용시 sendMail부분에서 다음과 같은 에러가 발생

org.springframework.mail.MailSendException: Mail server connection failed; nested exception is javax.mail.NoSuchProviderException: No provider for SMTP. Failed messages: javax.mail.NoSuchProviderException: No provider for SMTP at org.springframework.mail.javamail.JavaMailSenderImpl.doSend(JavaMailSenderImpl.java:446) ~[spring-context-support-5.1.2.RELEASE.jar!/:5.1.2.RELEASE] at
.
.
.
Caused by: javax.mail.NoSuchProviderException: No provider for SMTP
at javax.mail.Session.getProvider(Session.java:545) ~[javax.mail-1.6.2.jar!/:1.6.2] at 
.
.

 

소스코드

    @Bean
    public JavaMailSenderImpl mailSender() {
        JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();

        javaMailSender.setProtocol("SMTP");
        javaMailSender.setHost("127.0.0.1");
        javaMailSender.setPort(25);

        return javaMailSender;
    }

문제의 원인은 javaMailSender.setProtocol("SMTP"); 이부분이였다.

setProtocol의 "SMTP"를 "smtp" 소문자로 변경해주면 해결된다.

해결책

"SMTP" => "smtp"

이유

JavaMailSenderImpl 파일을 들어가보면 알 수 있다. 내부에 DEFAULT_PROTOCOL 이 소문자로 할당되어있다.

public class JavaMailSenderImpl implements JavaMailSender {
    public static final String DEFAULT_PROTOCOL = "smtp";
    

항상 문제가 발생했을 때 문제 해결에 그치지 말고 이유에 대해서도 꼭 짚고 넘어가도록 하자!!!!

문제 해결보다 중요한게 원인 파악 이라고 생각한다.

반응형

+ Recent posts