기본 콘텐츠로 건너뛰기

Spring Redis Cluster Configuration

# build.gradle

compile 'org.springframework.data:spring-data-redis'
compile 'biz.paluch.redis:lettuce:4.5.0.Final'


#RedisConfiguration
@Configuration@
EnableRedisRepositories(basePackageClasses = { MyAppDomains.class })
public class RedisConfiguration {

    @Value("${spring.redis.host}")
    private String redisHost;
    @Value("${spring.redis.port}")
    private int redisPort;

    @Bean    
    public RedisConnectionFactory myRedisConnectionFactory() {
        RedisClusterConfiguration clusterConfig = new RedisClusterConfiguration();
        clusterConfig.clusterNode(redisHostredisPort);
        return new MyLettuceConnectionFactory(clusterConfig);    
    }

    @Bean    
    @ConditionalOnMissingBean(name "redisTemplate")
    @Primary    
    public RedisTemplate<??> redisTemplate(RedisConnectionFactory myRedisConnectionFactory) {
        RedisTemplate<byte[], byte[]> template = new RedisTemplate<>();
        template.setConnectionFactory(myRedisConnectionFactory);
        return template;
    }

    @Bean
    public CustomConversions redisCustomConversions() {
        return new CustomConversions(Arrays.asList(new MyReadConverter(), new MyWriteConverter()));
    }

}


MyLettuceConnectionFactory
@Configuration
public class MyLettuceConnectionFactory extends LettuceConnectionFactory {

    public MyLettuceConnectionFactory() { }

    public MyLettuceConnectionFactory(RedisClusterConfiguration clusterConfig) {
        super(clusterConfig);
    }

    @Override
    public void afterPropertiesSet() {
        super.afterPropertiesSet();
        DirectFieldAccessor accessor = new DirectFieldAccessor(this);
        AbstractRedisClient client = (AbstractRedisClient) accessor.getPropertyValue("client");
        if(client instanceof RedisClusterClient){
            RedisClusterClient clusterClient = (RedisClusterClient) client;
            ClusterTopologyRefreshOptions topologyRefreshOptions = ClusterTopologyRefreshOptions.builder()
                    .enablePeriodicRefresh(10TimeUnit.MINUTES)
                    .enableAllAdaptiveRefreshTriggers()
                    .build();
            ClusterClientOptions clusterClientOptions = ClusterClientOptions.builder()
                    .validateClusterNodeMembership(false)
                    .topologyRefreshOptions(topologyRefreshOptions)
                    .build();
            clusterClient.setOptions(clusterClientOptions);
        }
    }
}



# Entity
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@RedisHash("my:categories")
@ToString
public class Category {

    @Id
    private String id;
    @Indexed
   private int level;
    @Indexed
    private String parentId;
    private Map<IntegerString> parentNameByLevel;
    @Indexed
    private String documentType;
}



# Converter

@Component
@WritingConverter
public class MyWriteConverter implements Converter<Category, byte[]> {

    private final Jackson2JsonRedisSerializer<Category> serializer;
    public MyWriteConverter() {
        serializer new Jackson2JsonRedisSerializer<>(Category.class);
        serializer.setObjectMapper(new ObjectMapper());
    }

    @Override
    public byte[] convert(Category value) {
        return serializer.serialize(value);
    }
}
@Component
@ReadingConverter
public class MyReadConverter implements Converter<byte[]Category> {

    private final Jackson2JsonRedisSerializer<Category> serializer;
    public MyReadConverter() {
        serializer new Jackson2JsonRedisSerializer<>(Category.class);
        serializer.setObjectMapper(new ObjectMapper());
   }

    @Override
    public Category convert(byte[] value) {
        return serializer.deserialize(value);
    }
}


# Repository

public interface CategoryRepository extends CrudRepository<CategoryString> {
    List<Category> findByDocumentType(String documentType);
}

댓글

이 블로그의 인기 게시물

[JPA] deleted instance passed to merge

org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.ObjectDeletedException:   deleted instance passed to merge: 위와 같은 에러가 발생... em.remove(user)를 호출하면 user는 영속성 컨텍스트에서 제거된다. (Object is already marked for being deleted) 이후 트랜잭션을 커믹해서 플러시를 호출하면 실제 데이터베이스에 삭제 쿼리를 전달한다. 하지만 삭제된 엔티티를 한 트랜잭션내에서 다시 삭제할려고하면 해당 익셉션이 발생한다. 참조 : 자바 ORM 표준 JPA 프로그래밍

xsl-fo를 이용한 pdf 생성기술

1. PDF 생성 기술 개발을 위해 적용가능한 오픈소스 1)  pdfbox - http://pdfbox.apache.org/ - License : Apache License Version 2.0 2)  iText - http://itextpdf.com/ - License : APGL License 3)  Apache FOP - http://xmlgraphics.apache.org/fop/ -> 유지보수 비용은 높지만, 무료이며 한글이 출력 가능한 Apache FOP를 적용 2. XSL-FO를 이용하여 PDF를 어떻게 생성 하는지 설명 * XSL-FO의 기본 프로세스 용어 설명 1) XSLT - XML 문서를 다른 XML 문서로 변환하는데 사용하는 XML 기반의 언어 - 원본 문서는 변경되지 않으며, 원본 문서를 기반으로 새로운 문서를 생성 2) XSL-FO - XSL-FO는 종이, 화면 등 다양한 매체에 출력 하기 위한 XML 기반의 마크업 언어 - 사용자는 XSL-FO를 통해 어떻게 정보가 PDF에 출력되는지 확인 가능 3) XSL-FO Formatter - XSL-FO 문서를 최종 결과물인 PDF(다른 매체도 가능)문서로 변환할 수 있는 Formatter 간략하게 애기하면,  XSL-FO를 Formatter로 변환하게 되면 PDF가 생성되며,  XSL-FO는 사용자가 직접 작성할 수도 있고 XML source와 XSLT stylesheet를 이용하여 동적으로 생성 가능하다. 3. 간단한 예제로 정리 1) 필요한 데이터를 XML에 기술한다. XML file  <?xml version="1.0" encoding="UTF-8"?> <root>   <name>홍길동</name> </root>  ...