레이블이 Java인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Java인 게시물을 표시합니다. 모든 게시물 표시

2018년 2월 28일 수요일

Async Method Junit Test

When making junit test, it's hard to test async method.
I introduce the way to test async method by changing async to sync task executor.

@Service
@Slf4j
public class TestServiceImpl implements TestService {

    @Autowired
    private RestTemplate restTemplate;

    @Override
    @Async
    public void getString() {

        log.info("start");
        restTemplate.getForEntity("http://www.test.com", String.class);
    }
}

We will test this async method as above.

@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class TestServiceTest {

    @Configuration
    @Import(AsyncTestApplication.class)
    static class ContextConfiguration {
        @Bean
        @Primary
        public Executor executor() {
            return new SyncTaskExecutor();
        }
    }

    @Autowired
    private TestService testService;

    @MockBean
    private RestTemplate restTemplate;

    @Test
    public void testGetString() {

        //given
        given(restTemplate.getForEntity(anyString(), eq(String.class))).willReturn(new ResponseEntity(HttpStatus.OK));

        //when
        testService.getString();

        //then
        verify(restTemplate, times(1)).getForEntity(anyString(), eq(String.class));
    }
}


By using Configuration annotation, you can set the junit test config.
I will change the asyncExecutor to syncTaskExecutor,so that we could check the internal logic of async method.


2018-03-01 15:54:47.729  INFO 6836 --- [           main] o.b.test.service.impl.TestServiceImpl    : start

You can find your test case passed.


You can download whole project from below git url.

https://gitlab.com/shashaka/async-junit-test-project

2017년 11월 27일 월요일

filtering custom exception stacktrace

When you are using custom exception class,
there are a lot of stacktrace when it occurred.
So we can override the method named fillInStackTrace() as below.

 @Override
    public synchronized Throwable fillInStackTrace() {
        return this;
    }

After that, when exception occured, it shows just exception message.

Caused by: org.blog.test.common.CustomException: custom exception occured

all the example is in the below url.

https://gitlab.com/shashaka/custom-exception-project

2017년 4월 8일 토요일

javax.persistence.RollbackException: Transaction marked as rollbackOnly

Spring에서 위와 같은 RollbackException이 발생하는 경우에 대해서 알아보도록 하자.
먼저 아래와 같은 두 개의 서비스가 있다.

ExceptionService의 throwException() 메소드는 NullPointerException을 발생시키는 메소드이다.
UserService의 addUser 메소드는 ExceptionService.throwException()을 호출하고 user를 add하는 메소드이다.
다만, exception을 처리하기 위해 try-catch 문으로 해당 exception을 처리한 상태이다.

아래와 같은 상황에서 userService.addUser()를 호출하면 어떻게 될까?

- UserServiceImpl.java

@Service
@Transactional
@Slf4j
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private ExceptionService exceptionService;

    @Override
    public User addUser(String name) {
        try {
            exceptionService.ThrowException();
        } catch (Exception e) {
            log.info("Exception occured");
        }
        return userRepository.save(new User(name));
    }
}

- ExceptionServiceImpl.java

@Transactional
@Service
public class ExceptionServiceImpl implements ExceptionService {

    @Override
    public void ThrowException() throws Exception {
        throw new NullPointerException();
    }
}


아래와 같이 장황한 RollbackException이 발생하게 된다.
왜 이런 상황이 발생되는 지 순서대로 알아보자.

- Output

javax.persistence.RollbackException: Transaction marked as rollbackOnly
 at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:58) ~[hibernate-entitymanager-5.0.9.Final.jar:5.0.9.Final]
 at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:517) ~[spring-orm-4.3.2.RELEASE.jar:4.3.2.RELEASE]
 at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:761) ~[spring-tx-4.3.2.RELEASE.jar:4.3.2.RELEASE]
 at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730) ~[spring-tx-4.3.2.RELEASE.jar:4.3.2.RELEASE]
 at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:483) ~[spring-tx-4.3.2.RELEASE.jar:4.3.2.RELEASE]
 at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:290) ~[spring-tx-4.3.2.RELEASE.jar:4.3.2.RELEASE]
 at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) ~[spring-tx-4.3.2.RELEASE.jar:4.3.2.RELEASE]
 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.2.RELEASE.jar:4.3.2.RELEASE]
 at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:655) ~[spring-aop-4.3.2.RELEASE.jar:4.3.2.RELEASE]
 at org.blog.test.user.service.impl.UserServiceImpl$$EnhancerBySpringCGLIB$$dcb2eb86.addUser() ~[main/:na]
 at org.blog.test.user.controller.UserController.addUser(UserController.java:18) ~[main/:na]

우리는 두 서비스 모두 @transactional 이 선언되어 있다는 것에 주목할 필요가 있다.

실제 transaction의 흐름을 살펴보자~!!

1. userService.addUser() 가 호출되면서, transaction A가 시작됨
2. 해당 메소드 내의 exceptionService.throwException() 메소드가 호출됨
3. throwException 메소드 역시 @transactional이 선언되어 있기 때문에, 현재 transaction을 확인
4. @transactional의 기본값은 Propagation.REQUIRED 이기 때문에, 기존에 실행된 transaction A를 그대로 사용

- public static final Propagation REQUIRED
Support a current transaction, create a new one if none exists. Analogous to EJB transaction attribute of the same name.
This is the default setting of a transaction annotation.

5. NullPointerException이 발생하면서, 해당 transaction A를 rollbackOnly로 설정 후, userService.addUser()로 돌아감
6. userRepository.save(new User(name)); 가 실행됨.
7. userService.addUser()에서는 해당 NullPointerException이 try-catch 문으로 처리가 되었기 때문에 transaction을 commit 시도.
8. transaction이 rollbackOnly로 설정되었기 때문에 commit 실패하면서, RollbackException 발생

이에 대한 해결 방법은 여러가지가 있다.

1. ExceptionService 를 async로 실행
2. ExceptionService 의 @transactional 제거
3. ExceptionService 의 transaction 의 propagation 변경

그 중 3번에 대해 알아보면,
아래와 같이 transaction의 propagation을 REQUIRES_NEW로 바꾸면 새로운 transaction을 시작하기 때문에,
위와 같은 에러가 발생하지는 않는다.
하지만, 이 방법이 전체 method의 flow에 적합한지 검토 후, 적용하는 것이 좋을 것 같다.

@Transactional(propagation = Propagation.REQUIRES_NEW)
@Service
public class ExceptionServiceImpl implements ExceptionService {

- Output

2017-04-08 20:13:42.193  INFO 13552 --- [nio-8080-exec-8] o.b.t.user.service.impl.UserServiceImpl  : Exception occured
2017-04-08 20:13:42.198  INFO 13552 --- [nio-8080-exec-8] jdbc.sqltiming                           : insert into user (name) values ('femeo') 
 {executed in 2 msec}

2017년 4월 7일 금요일

LinkedList simple implementation

- java file

package org.blog.test;

public class TestApplication {
    public static void main(String[] args) {

        MyLinkedList myLinkedList = new MyLinkedList();
        myLinkedList.add("1");
        myLinkedList.add("2");
        myLinkedList.add("3");
        myLinkedList.add("4");
        myLinkedList.add("5");
        myLinkedList.add(2, "2.5");
        myLinkedList.remove(3);
        for (int i = 0; i < myLinkedList.size(); i++) {
            System.out.println(myLinkedList.get(i).getData());
        }
    }
}

class MyLinkedList {

    private Node head;

    private Node tail;

    private int size;

    public MyLinkedList() {
        this.head = null;
        this.tail = null;
        this.size = 0;
    }

    public void addFirst(Object data) {
        Node myNode = new Node(data);
        if (this.size == 0) {
            this.head = myNode;
            this.tail = myNode;
        } else {
            myNode.next = head;
            head.prev = myNode;
            this.head = myNode;
        }
        size++;
    }

    public void add(Object data) {
        if (this.size() == 0) {
            addFirst(data);
        } else {
            Node newNode = new Node(data);
            this.tail.next = newNode;
            newNode.prev = this.tail;
            this.tail = newNode;
            size++;
        }
    }

    public void add(int index, Object data) {
        if (index == 0) {
            addFirst(data);
        } else if (index == this.size) {
            add(data);
        } else {
            Node newNode = new Node(data);
            Node currentNode = get(index);
            newNode.prev = currentNode.prev;
            newNode.prev.next = newNode;
            newNode.next = currentNode;
            currentNode.prev = newNode;
            size++;
        }
    }

    public void removeFirst() {
        this.head = this.head.next;
        this.head.prev = null;
        this.size--;
    }

    public void remove() {
        this.tail = this.tail.prev;
        this.tail.next = null;
        size--;
    }

    public void remove(int index) {
        if (index == 0) {
            removeFirst();
        } else if (index == this.size - 1) {
            remove();
        } else {
            Node prevNode = get(index - 1);
            Node nextNode = get(index + 1);
            prevNode.next = nextNode;
            nextNode.prev = prevNode;
            size--;
        }
    }

    public Node get(int index) {

        if (index < (this.size / 2)) {
            Node ret = this.head;
            for (int i = 0; i < index; i++) {
                ret = ret.next;
            }
            return ret;
        } else {
            Node ret = this.tail;
            for (int i = size - 1; i > index; i--) {
                ret = ret.prev;
            }
            return ret;
        }
    }

    public int size() {
        return this.size;
    }

    class Node {

        private Object data;

        private Node prev;

        private Node next;

        public Node(Object data) {
            this.data = data;
            this.prev = null;
            this.next = null;
        }

        public Object getData() {
            return this.data;
        }
    }
}

- output

1
2
2.5
4
5

Process finished with exit code 0

ArrayList simple implementation

- java file

package org.blog.test;

public class TestApplication {
    public static void main(String[] args) {
        MyArrayList myArrayList = new MyArrayList();
        myArrayList.add("sdfd");
        myArrayList.add("sdfd1");
        myArrayList.add("sdfd2");
        myArrayList.remove(1);
        myArrayList.add(1, "sdfd1");
        myArrayList.add(1, "sdfd0.5");
        myArrayList.add(1, "sdfd0.3");
        myArrayList.remove(2);
        for (int i = 0; i < myArrayList.size(); i++) {
            System.out.println(myArrayList.get(i));
        }
        System.out.println(myArrayList.size());
    }
}

class MyArrayList {

    private int size;

    private Object[] data;

    public MyArrayList() {
        this.size = 0;
        this.data = new Object[100];
    }

    public void add(Object data) {
        this.data[this.size] = data;
        this.size++;
    }

    public void add(int index, Object data) {
        for (int i = this.size - 1; i >= index; i--) {
            this.data[i + 1] = this.data[i];
        }
        this.data[index] = data;
        this.size++;
    }

    public void remove(int index) {
        for (int i = index + 1; i <= this.size - 1; i++) {
            this.data[i - 1] = this.data[i];
        }
        this.data[this.size - 1] = -1;
        this.size--;
    }

    public Object get(int index) {
        return this.data[index];
    }

    public int size() {
        return this.size;
    }
}
- output
sdfd
sdfd0.3
sdfd1
sdfd2
4

Process finished with exit code 0

2017년 3월 31일 금요일

Make redis client by using lettuce

You can use java redis client by using lettuce.

- Execution file

package org.blog.test;

import com.lambdaworks.redis.RedisClient;
import lombok.extern.slf4j.Slf4j;
import org.blog.test.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
@Slf4j
public class LettuceApplication implements CommandLineRunner {
    public static void main(String[] args) {
        SpringApplication.run(LettuceApplication.class, args);
    }

    @Bean
    public RedisClient redisClient() {
        return RedisClient.create("redis://localhost");
    }

    @Autowired
    private RedisService redisService;

    @Override
    public void run(String... args) throws Exception {
        log.info("redisService.ping() : {}", redisService.ping());
        log.info("redisService.set(\"key\", \"hello redis~!!\") : {}", redisService.set("key", "hello redis~!!"));
        log.info("redisService.get(\"key\") : {}", redisService.get("key"));
    }
}


- redisService

package org.blog.test.service;

import com.lambdaworks.redis.RedisClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class RedisServiceImpl implements RedisService {

    @Autowired
    private RedisClient redisClient;

    @Override
    public String ping() {
        return redisClient.connect().sync().ping();
    }

    @Override
    public String get(String key) {
        return redisClient.connect().sync().get(key);
    }

    @Override
    public String set(String key, String value) {
        return redisClient.connect().sync().set(key, value);
    }
}

- output

2017-03-31 21:28:30.035  INFO 4376 --- [           main] org.blog.test.LettuceApplication         : redisService.ping() : PONG
2017-03-31 21:28:30.059  INFO 4376 --- [           main] org.blog.test.LettuceApplication         : redisService.set("key", "hello redis~!!") : OK
2017-03-31 21:28:30.080  INFO 4376 --- [           main] org.blog.test.LettuceApplication         : redisService.get("key") : hello redis~!!

2017년 3월 25일 토요일

Using JMX to monitor asyncTaskExecutor

You can monitor your taskExecutor by using spring jmx.

- Config file

package org.blog.test;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.jmx.export.MBeanExporter;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.HashMap;
import java.util.Map;

@SpringBootApplication
@Slf4j
public class JmxApplication {
    public static void main(String[] args) {
        SpringApplication.run(JmxApplication.class, args);
    }

    @Bean
    public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
        return new ThreadPoolTaskExecutor() {{
            setCorePoolSize(2);
            setMaxPoolSize(5);
            setQueueCapacity(10);
            initialize();
        }};
    }

    @Bean
    public MBeanExporter myMbeanExporter() {
        return new MBeanExporter() {{
            Map beans = new HashMap<>();
            beans.put("org.blog.test:name=threadPoolTaskExecutor", threadPoolTaskExecutor().getThreadPoolExecutor());
            setBeans(beans);
        }};
    }
}

You can declare the bean as MBeanExporter, and then register threadPoolTaskExecutor as one of beans.
By using jconsole in JAVA_HOME/bin/jconsole, you can monitor your jvm application.
You can find the declared Mbean in Mbean tab.

2017년 3월 15일 수요일

RestTemplate connection pool setting

You can set the connection pool to restTemplate by using connection manager.


- Configuration

package org.blog.test;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@Slf4j
public class RestTemplateApplication {
    public static void main(String[] args) {
        SpringApplication.run(RestTemplateApplication.class, args);
    }

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate() {{
            setRequestFactory(new HttpComponentsClientHttpRequestFactory(HttpClientBuilder
                    .create()
                    .setConnectionManager(new PoolingHttpClientConnectionManager() {{
                        setDefaultMaxPerRoute(20);
                        setMaxTotal(200);
                    }}).build()));
        }};
    }
}

2017년 2월 10일 금요일

RestTemplate proxy setting by active profile each

You can set the proxy to use RestTemplate.

- RestLoggingApplication.java

package org.blog.test;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
import org.apache.http.impl.client.HttpClientBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

import java.util.Arrays;
import java.util.HashSet;

@SpringBootApplication
@Slf4j
public class RestLoggingApplication {
    public static void main(String[] args) {
        SpringApplication.run(RestLoggingApplication.class, args);
    }

    @Autowired
    private Environment environment;

    @Bean
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = new RestTemplate();
        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
        if (new HashSet<>(Arrays.asList(environment.getActiveProfiles())).contains("local")) {
            log.info("set local proxy");
            httpClientBuilder.setProxy(new HttpHost("proxy.example.com", 8080, null));
        }
        restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClientBuilder.build()));
        return restTemplate;
    }
}


- Result

2017-02-11 01:49:31.316  INFO 2040 --- [           main] org.blog.test.RestLoggingApplication     : set local proxy
2017-02-11 01:49:32.139  INFO 2040 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@1372ed45: startup date [Sat Feb 11 01:49:28 KST 2017]; root of context hierarchy
2017-02-11 01:49:32.203  INFO 2040 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/test],methods=[GET]}" onto public java.lang.String org.blog.test.restcall.controller.RestTestController.testPostRest()
2017-02-11 01:49:32.203  INFO 2040 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity
org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2017-02-11 01:49:32.203  INFO 2040 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2017-02-11 01:49:32.241  INFO 2040 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2017-02-11 01:49:32.241  INFO 2040 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2017-02-11 01:49:32.288  INFO 2040 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2017-02-11 01:49:32.457  INFO 2040 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2017-02-11 01:49:32.541  INFO 2040 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2017-02-11 01:49:32.541  INFO 2040 --- [           main] org.blog.test.RestLoggingApplication     : Started RestLoggingApplication in 4.93 seconds (JVM running for 5.699)

RestTemplate Logging

You can set the restTemplate logging interceptor by ClientHttpRequestInterceptor.


- Structure




- RestTemplateConfig.java

package org.blog.test.config;

import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.RestTemplate;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Configuration
@Slf4j
public class RestTemplateConfig {

    @Bean
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = new RestTemplate();

        List interceptors = new ArrayList<>();
        interceptors.add(new ClientHttpRequestInterceptor() {
            @Override
            public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
                ClientHttpResponse response = execution.execute(request, body);
                doLog(request, body, response);
                return response;
            }

            private void doLog(HttpRequest request, byte[] body, ClientHttpResponse response) throws IOException {
                log.info("[Request] [{}]  {}, Headers : [{}], Body : [{}]", request.getMethod(), request.getURI(), request.getHeaders(), new String(body, Charset.forName("UTF-8")));
                log.info("[Response] [{}], Headers : [{}], Body : [{}] ", response.getStatusCode(), response.getHeaders(), new BufferedReader(new InputStreamReader(response.getBody())).readLine())
                ;
            }
        });
        restTemplate.setInterceptors(interceptors);
        return restTemplate;
    }
}

- RestCallServiceImpl.java

package org.blog.test.restcall.service.impl;

import org.blog.test.restcall.model.TestRequest;
import org.blog.test.restcall.service.RestCallService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.lang.reflect.Type;
import java.nio.charset.Charset;

@Service
public class RestCallServiceImpl implements RestCallService {

    @Autowired
    private RestTemplate restTemplate;

    @Override
    public String getTestString() {
        ResponseEntity responseEntity = restTemplate.exchange("http://google.com", HttpMethod.GET, null, String.class);
        return responseEntity.getBody();
    }
}


- Result

2017-02-10 17:10:48.078  INFO 4432 --- [nio-8080-exec-1] org.blog.test.config.RestTemplateConfig  : [Request] [GET]  http://google.com, Headers : [{Accept=[text/plain, application/json, application/*+json, */*], Content-Length=[0]}], Body : []
2017-02-10 17:10:48.092  INFO 4432 --- [nio-8080-exec-1] org.blog.test.config.RestTemplateConfig  : [Response] [200], Headers : [{Date=[Fri, 10 Feb 2017 08:10:12 GMT], Expires=[-1], Cache-Control=[private, max-age=0], Content-Type=[text/html; charset=EUC-KR], P3P=[CP="This is not a P3P policy! See https://www.google.com/support/accounts/answer/151657?hl=en for more info."], Server=[gws], X-XSS-Protection=[1; mode=block], X-Frame-Options=[SAMEORIGIN], Set-Cookie=[NID=96=b2LgtIg7PncSQLK0OeCPOKcSwmpWyMJN_3SU6QSKQ30UbUQ3jTIk5TCFgGgbf-rYt-nlWjSZzGoyfnTywJOkmavt3WDqyVexDSxT8rOLHn3-eqDiK6Cps5hYKckQCzsD; expires=Sat, 12-Aug-2017 08:10:12 GMT; path=/; domain=.google.co.kr; HttpOnly], Accept-Ranges=[none], Vary=[Accept-Encoding], Transfer-Encoding=[chunked]}], Body : [.....]

2016년 12월 2일 금요일

Java List convert to Map

You can convert list to map by using java collector.

- JpaApplication.java

package org.blog.test;

import lombok.extern.slf4j.Slf4j;
import org.blog.test.user.entity.User;
import org.blog.test.user.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collector;
import java.util.stream.Collectors;

@SpringBootApplication
@Slf4j
public class JpaApplication implements CommandLineRunner {
    public static void main(String[] args) {
        SpringApplication.run(JpaApplication.class, args);
    }

    @Autowired
    private UserService userService;

    @Override
    public void run(String... args) throws Exception {

        List users = new ArrayList<>();
        users.add(new User(1L, "name1"));
        users.add(new User(2L, "name2"));
        users.add(new User(3L, "name3"));

        Map userMap = users.stream().collect(Collectors.toMap(x -> x.getId(), x -> x));

        log.info("userMap : [{}]", userMap);

    }
}

- result

2016-12-03 03:04:49.178  INFO 6344 --- [           main] org.blog.test.JpaApplication             : userMap : [{1=User(id=1, name=name1), 2=User(id=2, name=name2), 3=User(id=3, name=name3)}]

2016년 9월 19일 월요일

Junit controller layer test

You can do the test by using spring boot junit test.

- structure
















- build.gradle

group 'org.blog.test'
version '1.0-SNAPSHOT'

apply plugin: 'java'
apply plugin: 'spring-boot'

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.4.0.RELEASE")
    }
}

repositories {
    mavenCentral()
}

dependencies {
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: '1.4.0.RELEASE'
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '1.4.0.RELEASE'
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa', version: '1.4.0.RELEASE'
    compile group: 'com.h2database', name: 'h2', version: '1.4.192'
    compile group: 'org.projectlombok', name: 'lombok', version: '1.16.10'
    compile group: 'junit', name: 'junit', version: '4.12'
}


- TestController.java

package org.blog.test.controller;

import org.blog.test.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

    @Autowired
    private TestService testService;

    @GetMapping("/test/{name}")
    public String getByName(@PathVariable String name) {
        return String.valueOf(testService.getTestTableByName(name));
    }
}




- JunitApplication.java

package org.blog.test;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class JunitApplication {
    public static void main(String[] args) {
        SpringApplication.run(JunitApplication.class, args);
    }
}


- TestControllerTest.java

package org.blog.test.controller;

import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import java.util.ArrayList;
import java.util.List;

import org.blog.test.entity.TestTable;
import org.blog.test.service.TestService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;

@RunWith(SpringRunner.class)
@WebMvcTest(TestController.class)
public class TestControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private TestService testService;

    @Test
    public void getByName() throws Exception {
        //Given
        TestTable testTable = new TestTable("test");
        List resultList = new ArrayList<>();
        resultList.add(testTable);

        given(this.testService.getTestTableByName("test")).willReturn(resultList);

        //When
        this.mockMvc.perform(get("/test/test").accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk());
    }
}




- result

MockHttpServletRequest:
      HTTP Method = GET
      Request URI = /test/test
       Parameters = {}
          Headers = {Accept=[application/json]}

Handler:
             Type = org.blog.test.controller.TestController
           Method = public java.lang.String org.blog.test.controller.TestController.getByName(java.lang.String)

Async:
    Async started = false
     Async result = null

Resolved Exception:
             Type = null

ModelAndView:
        View name = null
             View = null
            Model = null

FlashMap:
       Attributes = null

MockHttpServletResponse:
           Status = 200
    Error message = null
          Headers = {Content-Type=[application/json;charset=UTF-8], Content-Length=[31]}
     Content type = application/json;charset=UTF-8
             Body = [TestTable(id=null, name=test)]
    Forwarded URL = null
   Redirected URL = null
          Cookies = []
 

Junit service layer test

You can do the test by using spring boot junit test.

- structure


















- build.gradle

group 'org.blog.test'
version '1.0-SNAPSHOT'

apply plugin: 'java'
apply plugin: 'spring-boot'

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.4.0.RELEASE")
    }
}

repositories {
    mavenCentral()
}

dependencies {
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: '1.4.0.RELEASE'
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '1.4.0.RELEASE'
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa', version: '1.4.0.RELEASE'
    compile group: 'com.h2database', name: 'h2', version: '1.4.192'
    compile group: 'org.projectlombok', name: 'lombok', version: '1.16.10'
    compile group: 'junit', name: 'junit', version: '4.12'
}


- TestService.java

package org.blog.test.service;

import org.blog.test.entity.TestTable;

import java.util.List;

public interface TestService {

    List getTestTableByName(String name);
}



- TestServiceImpl.java

package org.blog.test.service.impl;

import org.blog.test.entity.TestTable;
import org.blog.test.repository.TestRepository;
import org.blog.test.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class TestServiceImpl implements TestService {

    @Autowired
    private TestRepository testRepository;

    @Override
    public List getTestTableByName(String name) {
        return testRepository.findByName(name);
    }
}


- JunitApplication.java

package org.blog.test;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class JunitApplication {
    public static void main(String[] args) {
        SpringApplication.run(JunitApplication.class, args);
    }
}


- TestServiceTest.java

package org.blog.test.service;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;

import java.util.ArrayList;
import java.util.List;

import org.blog.test.entity.TestTable;
import org.blog.test.repository.TestRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@WebMvcTest(TestService.class)
public class TestServiceTest {

    @MockBean
    private TestRepository testRepository;

    @Autowired
    private TestService testService;

    @Test
    public void getByName() {
        //Given
        List resultList = new ArrayList<>();
        resultList.add(new TestTable(1L, "test"));

        given(testRepository.findByName("test")).willReturn(resultList);

        //When
        List result = testService.getTestTableByName("test");

        //Then
        assertThat(result).isEqualTo(resultList);
    }
}



- result

7:16:27: External tasks execution finished 'cleanTest test --tests org.blog.test.service.TestServiceTest'.
 

Junit data jpa test

You can do the test by using spring boot junit test.

- structure















- build.gradle

group 'org.blog.test'
version '1.0-SNAPSHOT'

apply plugin: 'java'
apply plugin: 'spring-boot'

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.4.0.RELEASE")
    }
}

repositories {
    mavenCentral()
}

dependencies {
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: '1.4.0.RELEASE'
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '1.4.0.RELEASE'
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa', version: '1.4.0.RELEASE'
    compile group: 'com.h2database', name: 'h2', version: '1.4.192'
    compile group: 'org.projectlombok', name: 'lombok', version: '1.16.10'
    compile group: 'junit', name: 'junit', version: '4.12'
}


- TestTable.java

package org.blog.test.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TestTable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String name;

    public TestTable(String name) {
        this.name = name;
    }
}


- TestRepository.java

package org.blog.test.repository;

import org.blog.test.entity.TestTable;
import org.springframework.data.repository.CrudRepository;

import java.util.List;

public interface TestRepository extends CrudRepository {

    List findByName(String name);
}


- JunitApplication.java

package org.blog.test;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class JunitApplication {
    public static void main(String[] args) {
        SpringApplication.run(JunitApplication.class, args);
    }
}


- TestRepositoryTest.java

package org.blog.test.repository;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;

import java.util.List;

import org.blog.test.entity.TestTable;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@DataJpaTest
public class TestRepositoryTest {

    @Autowired
    private TestEntityManager testEntityManager;

    @Autowired
    private TestRepository testRepository;

    @Test
    public void findByName() {
        //Given
        TestTable testTable = new TestTable("test");
        this.testEntityManager.persist(testTable);

        //When
        List result = testRepository.findByName("test");

        //Then
        assertThat(result.get(0), is(testTable));
    }
}



- result

7:06:47: External tasks execution finished 'cleanTest test --tests org.blog.test.repository.TestRepositoryTest'.
 

2016년 8월 25일 목요일

Setting in-memory queue as camel seda

You can set the in-memory queue by using camel seda.

- Structure















- build.gradle

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.4.0.RELEASE")
    }
}

apply plugin: 'java'
apply plugin: 'spring-boot'

repositories {
    mavenCentral()
}

dependencies {
    compile('org.springframework.boot:spring-boot-starter-web')
    compile group: 'org.projectlombok', name: 'lombok', version: '1.16.10'
    compile group: 'org.apache.camel', name: 'camel-spring-boot-starter', version: '2.17.0'
}

- TestRouter.java

package org.blog.test.route;

import lombok.extern.slf4j.Slf4j;
import org.apache.camel.CamelContext;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.spi.ExecutorServiceManager;
import org.apache.camel.spi.ThreadPoolProfile;
import org.apache.tomcat.util.threads.ThreadPoolExecutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class TestRouter extends RouteBuilder {

    @Override
    public void configure() throws Exception {
        from("seda:start?size=10").streamCaching().threads(10).process(exchange -> log.info("process message : [{}]", exchange.getIn().getBody())).end();
    }
}

- SedaApplication.java

package org.blog.test;

import lombok.extern.slf4j.Slf4j;
import org.apache.camel.CamelContext;
import org.apache.camel.Exchange;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.component.seda.SedaEndpoint;
import org.apache.camel.spi.ThreadPoolProfile;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;

@SpringBootApplication
@RestController
@Slf4j
public class SedaApplication {

    public static void main(String[] args) {
        SpringApplication.run(SedaApplication.class, args);
    }

    @Autowired
    private ProducerTemplate producerTemplate;

    @Autowired
    private CamelContext camelContext;


    @RequestMapping("/send")
    public String sendMessage() throws Exception {
        producerTemplate.sendBody("seda:start", "fewfe");
        SedaEndpoint sedaEndpoint = (SedaEndpoint) camelContext.getEndpoint("seda:start");
        StringBuilder builder = new StringBuilder();

        for (Exchange exchange : sedaEndpoint.getExchanges()) {
            builder.append(exchange.getIn().getBody());
        }
        return builder.toString();
    }

    @PostConstruct
    private void init() {
        ThreadPoolProfile profile = new ThreadPoolProfile();
        profile.setMaxPoolSize(10);
        profile.setDefaultProfile(true);
        profile.setId("customedProfile");
        camelContext.getExecutorServiceManager().setDefaultThreadPoolProfile(profile);
    }
}

- result

You can find that seda is working well.

2016년 8월 23일 화요일

Making queue service by using RabbitMq (publish/subscribe)

You can make publish/subscribe queue system by using rabbitmq.

- Structure















- build.gradle

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.4.0.RELEASE")
    }
}

apply plugin: 'java'
apply plugin: 'spring-boot'

repositories {
    mavenCentral()
}

dependencies {
    compile('org.springframework.boot:spring-boot-starter-web')
    compile group: 'org.projectlombok', name: 'lombok', version: '1.16.10'
    compile group: 'com.rabbitmq', name: 'amqp-client', version: '3.6.5'
}

- application.yml

spring:
  application:
    name: queue-server
server:
  port: 8080

- SendMessageService.java

package org.blog.test.queue.service;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import lombok.extern.slf4j.Slf4j;
import org.blog.test.queue.model.TopicType;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeoutException;

@Component
@Slf4j
public class SendMessageService {

    @Value("${message.queue.host:localhost}")
    private String messageQueueHost;

    @Value("${message.queue.port:5672}")
    private Integer messageQueuePort;

    @Value("${message.queue.connection.size:30}")
    private Integer connectionSize;

    private static ConnectionFactory connectionFactory;

    private static final String TOPIC_TYPE = "topic_message";

    @PostConstruct
    private void init() throws IOException, TimeoutException {
        configureConnection();
        configureQueue();
    }

    private void configureConnection() {
        connectionFactory = new ConnectionFactory();
        connectionFactory.setHost(messageQueueHost);
        connectionFactory.setPort(messageQueuePort);
        connectionFactory.setConnectionTimeout(20);
    }

    private void configureQueue() throws IOException, TimeoutException {
        Connection connection = connectionFactory.newConnection(Executors.newFixedThreadPool(connectionSize));
        Channel channel = connection.createChannel();
        channel.exchangeDeclare(TOPIC_TYPE, "topic");

        for (TopicType topicType : TopicType.values()) {
            channel.queueDeclare(topicType.getQueueType(), true, false, false, null);
            channel.queueBind(topicType.getQueueType(), TOPIC_TYPE, topicType.name());
        }

        channel.close();
        connection.close();
    }

    public void send(TopicType topicType, String message) throws IOException, TimeoutException {
        Connection connection = connectionFactory.newConnection(Executors.newFixedThreadPool(connectionSize));
        Channel channel = connection.createChannel();
        channel.basicPublish(TOPIC_TYPE, topicType.name(), null, message.getBytes());
        channel.close();
        connection.close();
        log.info("send topicType : [{}],message: [{}]", topicType.name(), message);
    }
}

- QueueMessageReciever.java

package org.blog.test.queue.service;

import com.rabbitmq.client.*;
import lombok.extern.slf4j.Slf4j;
import org.blog.test.queue.model.TopicType;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeoutException;

@Component
@Slf4j
public class QueueMessageReciever {

    @Value("${message.queue.host:localhost}")
    private String messageQueueHost;

    @Value("${message.queue.port:5672}")
    private Integer messageQueuePort;

    @Value("${message.queue.connection.size:30}")
    private Integer connectionSize;

    private static ConnectionFactory connectionFactory;

    @PostConstruct
    private void init() throws IOException, TimeoutException {
        connectionFactory = new ConnectionFactory();
        connectionFactory.setHost(messageQueueHost);
        connectionFactory.setPort(messageQueuePort);
        connectionFactory.setConnectionTimeout(20);

        for (TopicType topicType : TopicType.values()) {
            consume(topicType);
        }
    }

    private void consume(TopicType topicType) throws IOException, TimeoutException {
        Connection connection = connectionFactory.newConnection(Executors.newFixedThreadPool(connectionSize));
        Channel channel = connection.createChannel();

        Consumer consumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag,
                                       Envelope envelope,
                                       AMQP.BasicProperties properties,
                                       byte[] body)
                    throws IOException {
                String message = new String(body, "UTF-8");
                log.info("Received envelop : [{}], message : [{}]", envelope.getRoutingKey(), message);
            }
        };
        channel.basicConsume(topicType.getQueueType(), true, consumer);
    }
}

- QueueApplication.java

package org.blog.test;

import org.blog.test.queue.model.TopicType;
import org.blog.test.queue.service.SendMessageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

@SpringBootApplication
@RestController
public class QueueApplication {

    @Autowired
    private SendMessageService sendMessageService;

    public static void main(String[] args) {
        SpringApplication.run(QueueApplication.class, args);
    }

    @RequestMapping("/send/{topic}/{message}")
    public void sendMessage(@PathVariable("topic") String topic, @PathVariable("message") String message) throws IOException, TimeoutException {
        sendMessageService.send(TopicType.valueOf(topic.toUpperCase()), message);
    }
}

- TopicType.java

package org.blog.test.queue.model;

import lombok.AllArgsConstructor;
import lombok.Getter;


@AllArgsConstructor
@Getter
public enum TopicType {

    PUSH("PUSH_QUEUE"),
    EMAIL("EMAIL_QUEUE"),
    LOG("LOG_QUEUE");

    private String queueType;

}

- Result

You can find the subscribed log, and graph in rabbitmq console.

2016년 8월 20일 토요일

Making queue service by using RabbitMq

You can make the queue service by using rabbitmq like below.

- structure















- build.gradle

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.4.0.RELEASE")
    }
}

apply plugin: 'java'
apply plugin: 'spring-boot'

repositories {
    mavenCentral()
}

dependencies {
    compile('org.springframework.boot:spring-boot-starter-web')
    compile group: 'org.projectlombok', name: 'lombok', version: '1.16.10'
    compile group: 'com.rabbitmq', name: 'amqp-client', version: '3.6.5'
}


- application.yml

spring:
  application:
    name: queue-server
server:
  port: 8080


- SendMessageService.java

package org.blog.test.queue;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeoutException;

@Component
@Slf4j
public class SendMessageService {

    @Value("${message.queue.name:message_queue}")
    private String messageQueue;

    @Value("${message.queue.host:localhost}")
    private String messageQueueHost;

    @Value("${message.queue.port:5672}")
    private Integer messageQueuePort;

    @Value("${message.queue.connection.size:30}")
    private Integer connectionSize;

    private static ConnectionFactory connectionFactory;

    @PostConstruct
    private void init() {
        connectionFactory = new ConnectionFactory();
        connectionFactory.setHost(messageQueueHost);
        connectionFactory.setPort(messageQueuePort);
        connectionFactory.setConnectionTimeout(20);
    }

    public void send(String message) throws IOException, TimeoutException {
        Connection connection = connectionFactory.newConnection(Executors.newFixedThreadPool(connectionSize));
        Channel channel = connection.createChannel();
        channel.queueDeclare(messageQueue, false, false, false, null);
        channel.basicPublish("", messageQueue, null, message.getBytes());
        channel.close();
        connection.close();
        log.info("send message: [{}]", message);
    }
}


- QueueMessageReciever.java

package org.blog.test.queue;

import com.rabbitmq.client.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeoutException;

@Component
@Slf4j
public class QueueMessageReciever {

    @Value("${message.queue.name:message_queue}")
    private String messageQueue;

    @Value("${message.queue.host:localhost}")
    private String messageQueueHost;

    @Value("${message.queue.port:5672}")
    private Integer messageQueuePort;

    @Value("${message.queue.connection.size:30}")
    private Integer connectionSize;

    private static ConnectionFactory connectionFactory;

    @PostConstruct
    private void init() throws IOException, TimeoutException {
        connectionFactory = new ConnectionFactory();
        connectionFactory.setHost(messageQueueHost);
        connectionFactory.setPort(messageQueuePort);
        connectionFactory.setConnectionTimeout(20);
        consume();
    }

    private void consume() throws IOException, TimeoutException {
        Connection connection = connectionFactory.newConnection(Executors.newFixedThreadPool(connectionSize));
        Channel channel = connection.createChannel();
        channel.queueDeclare(messageQueue, false, false, false, null);

        Consumer consumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag,
                                       Envelope envelope,
                                       AMQP.BasicProperties properties,
                                       byte[] body)
                    throws IOException {
                String message = new String(body, "UTF-8");
                log.info("Received message : [{}]", message);
            }
        };
        channel.basicConsume(messageQueue, true, consumer);
    }
}


- QueueApplication.java

package org.blog.test;

import org.blog.test.queue.SendMessageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class QueueApplication implements CommandLineRunner {

    @Autowired
    private SendMessageService sendMessageService;

    public static void main(String[] args) {
        SpringApplication.run(QueueApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        sendMessageService.send("1");
        sendMessageService.send("2");
        sendMessageService.send("3");
    }
}

- result

You can find the result in rabbitmq console and server log.

2016년 1월 12일 화요일

Read and write JSON

1. adding dependency to pom.xml file


 com.googlecode.json-simple
 json-simple
 1.1
  


2. write JSON to file

import java.io.FileWriter;
import java.io.IOException;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
 
public class JsonSimpleExample {
     public static void main(String[] args) {
 
 JSONObject obj = new JSONObject();
 obj.put("name", "mkyong.com");
 obj.put("age", new Integer(100));
 
 JSONArray list = new JSONArray();
 list.add("msg 1");
 list.add("msg 2");
 list.add("msg 3");
 
 obj.put("messages", list);
 
 try {
 
  FileWriter file = new FileWriter("c:\\test.json");
  file.write(obj.toJSONString());
  file.flush();
  file.close();
 
 } catch (IOException e) {
  e.printStackTrace();
 }
 
 System.out.print(obj);
 
     }
 
}


output

{
 "age":100,
 "name":"mkyong.com",
 "messages":["msg 1","msg 2","msg 3"]
}

3. read JSON from file

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Iterator;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
 
public class JsonSimpleExample {
     public static void main(String[] args) {
 
 JSONParser parser = new JSONParser();
 
 try {
 
  Object obj = parser.parse(new FileReader("c:\\test.json"));
 
  JSONObject jsonObject = (JSONObject) obj;
 
  String name = (String) jsonObject.get("name");
  System.out.println(name);
 
  long age = (Long) jsonObject.get("age");
  System.out.println(age);
 
  // loop array
  JSONArray msg = (JSONArray) jsonObject.get("messages");
  Iterator iterator = msg.iterator();
  while (iterator.hasNext()) {
   System.out.println(iterator.next());
  }
 
 } catch (FileNotFoundException e) {
  e.printStackTrace();
 } catch (IOException e) {
  e.printStackTrace();
 } catch (ParseException e) {
  e.printStackTrace();
 }
 
     }
 
}

output

mkyong.com
100
msg 1
msg 2
msg 3


original source : http://www.mkyong.com/java/json-simple-example-read-and-write-json/

2016년 1월 8일 금요일

Spring JavaMail Sender [by using gmail account]

Project Architecture



pom.xml


 4.0.0
 org.blog.test
 email-by-gmail-project
 0.1.0
 
  org.springframework.boot
  spring-boot-starter-parent
  1.3.1.RELEASE
 
 
  
   org.springframework.boot
   spring-boot-starter-web
  
  
   org.projectlombok
   lombok
   1.16.6
  
  
   ch.qos.logback
   logback-core
   1.1.3
  
  
   ch.qos.logback
   logback-classic
  
  
   ch.qos.logback
   logback-access
  
  
   org.springframework
   spring-context-support
  
 
 
  1.8
 


application.properties

============================================
# Email Info
============================================
mail.host=smtp.gmail.com
mail.port=587
mail.username=test_account@gmail.com
mail.password=test_password

mail.password value is the app password of google 2-step verification

Email.java

package org.blog.test.model;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Email {

    private String sender;

    private String recipient;

    private String subject;

    private String content;
}

EmailService

package org.blog.test.email.service;

import javax.mail.MessagingException;

import org.blog.test.model.Email;

public interface EmailService {

    void send(Email email) throws MessagingException;
}

EmailServiceImpl.java

package org.blog.test.email.service.impl;

import java.util.Date;

import javax.mail.Message.RecipientType;
import javax.mail.MessagingException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import org.blog.test.email.service.EmailService;
import org.blog.test.model.Email;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;

@Service
public class EmailServiceImpl implements EmailService {

    @Autowired
    private JavaMailSender javaMailSender;

    @Override
    public void send(Email email) throws MessagingException {
        MimeMessage message = javaMailSender.createMimeMessage();
        message.setSubject(email.getSubject());
        message.setSender(new InternetAddress(email.getSender()));
        message.setRecipient(RecipientType.TO, new InternetAddress(email.getRecipient()));
        message.setText(email.getContent());

        message.setSentDate(new Date());

        javaMailSender.send(message);
    }

}

TestApplication.java

package org.blog.test;

import java.util.Properties;

import org.blog.test.email.service.EmailService;
import org.blog.test.model.Email;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;

@SpringBootApplication
public class TestApplication implements CommandLineRunner {

    @Value(value = "${mail.host}")
    private String javaMailHost;

    @Value(value = "${mail.port}")
    private int javaMailPort;

    @Value(value = "${mail.username}")
    private String javaMailUserName;

    @Value(value = "${mail.password}")
    private String javaMailPassword;

    @Autowired
    private EmailService emailService;

    public static void main(String[] args) {
        SpringApplication.run(TestApplication.class);
    }

    @Bean
    public JavaMailSender javaMailSender() {
        Properties mailSmtpStarttlsEnable = new Properties();
        mailSmtpStarttlsEnable.setProperty("mail.smtp.starttls.enable", "true");

        JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();      
        javaMailSender.setHost(javaMailHost);
        javaMailSender.setPort(javaMailPort);
        javaMailSender.setUsername(javaMailUserName);
        javaMailSender.setPassword(javaMailPassword);
        javaMailSender.setJavaMailProperties(mailSmtpStarttlsEnable);

        return javaMailSender;
    }

    @Override
    public void run(String... arg0) throws Exception {
        Email email = new Email("dont_reply", "test_recipient@naver.com", "test email", "this is the test");
        emailService.send(email);
    }
}

Execution Result

2015년 12월 22일 화요일

Guide to installing 3rd party JARs

거의 없지만, 가끔 3rd party Jar를 본인이 사용하고 있는 local repository에 추가하여야 할 경우가 있다.
예를 들면, Maven Central 같은 어떠한 공식적인 repository에서도 그 Jar 파일을 지원하지 않는 경우이다.
Apache Maven이 빌드 시에 정확히 그 파일을 가져오기 위해서는 정확한 장소에 해당 Jar는 위치해 있어야한다.
이러한 것을 쉽게 하기 위해서, Maven에서는 maven-install-plugin을 제공한다. 해당 Jar를 local repository에
install 하기 위해서는 아래의 command를 사용하면 된다.

mvn install:install-file -Dfile= -DgroupId= -DartifactId= -Dversion= -Dpackaging=

만약 pom 파일이 있다면, 아래 커맨드를 통해 pom 파일 역시 install 할 수 있다.

mvn install:install-file -Dfile= -DpomFile=

2.5 버전의 maven-install-plugin은 좀 더 나아졌다. 만약 Jar가 아파치 메이븐에 의해 빌드되어졌다면, 그 것은 META-INF 아래의 하위폴더에 pom.xml을 포함할 것이고,
이것은 기본적으로 읽히게 되어 있다. 이러한 경우에 당신에게 필요한 것은 아래의 커맨드가 전부이다.

mvn install:install-file -Dfile=

원본 출처 : https://maven.apache.org/guides/mini/guide-3rd-party-jars-local.html