반응형

enum 을 json으로 변환할 때 커스터마이징 하는 방법입니다.


Source

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
 
import com.fasterxml.jackson.annotation.JsonValue;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
 
public class Test {
  public enum Number {
    _1, _2, _3;
 
    @JsonValue
    public Integer toValue() {
      return Integer.parseInt(this.name().replace("_"""));
    }
  }
 
  public static void main(String[] args) throws IOException {
    ObjectMapper mapper = new ObjectMapper();
    Map<Number, String> map = new LinkedHashMap<>();
    map.put(Number._1, "one");
    map.put(Number._2, "two");
    String writeValueAsString = mapper.writer().writeValueAsString(map);
    System.out.println(writeValueAsString);
 
    Map<Number, String> map2 = mapper.readValue(writeValueAsString, new TypeReference<Map<Number, String>>() {
    });
    System.out.println(map2.get(Number._1));
    System.out.println(map2.get(Number._2));
  }
}


Result

1
2
3
{"1":"one","2":"two"}
one
two


Result Without @JsonValue

1
2
3
{"_1":"one","_2":"two"}
one
two


반응형
반응형

tomcat connection pool 사용 삽질기를 공유합니다. 

보통은 아래 tomcat-jdbc의 scope를 provided 로 해서 로컬 개발환경에서만 쓰고 운영할 환경이 Tomcat 이라면 별도로 라이브러리를 추가할 필요가 없습니다.

1
2
3
4
5
    <!-- tomcat-jdbc -->
    <dependency>
      <groupId>org.apache.tomcat</groupId>
      <artifactId>tomcat-jdbc</artifactId>
    </dependency>


이녀석은 tomcat-jdbc에 의존성이 걸려있는 라이브러리 입니다.

1
2
3
4
5
6
    <dependency>
      <groupId>org.apache.tomcat</groupId>
      <artifactId>tomcat-juli</artifactId>
      <version>8.5.6</version>
      <scope>compile</scope>
    </dependency>


그런데 이번에 운영환경이 Jeus인 곳에서 부가적으로 tomcat-jdbc를 같이 써보려고 시도했다가 고생좀 했습니다.

로컬 개발환경에서는 잘 돌아가던 녀석이 운영환경에 배포했더니 아래와 같은 처음 보는 오류를 발생시켰습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.IncompatibleClassChangeError: Found class org.apache.juli.logging.Log, but interface was expected
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:978)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
        at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:734)
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
 
        ...
 
Caused by: java.lang.IncompatibleClassChangeError: Found class org.apache.juli.logging.Log, but interface was expected
        at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:264)
        at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:203)
        at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:718)
        at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:650)
        at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:468)
        at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:143)
        at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118)
        at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107)
        at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131)
        at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111)
        at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77)
        at org.mybatis.spring.transaction.SpringManagedTransaction.openConnection(SpringManagedTransaction.java:82)
        at org.mybatis.spring.transaction.SpringManagedTransaction.getConnection(SpringManagedTransaction.java:68)


오류 내용인즉슨 org.apache.juli.logging.Log 클래스를 찾았는데 인터페이스만 있고 구현체가 없다는 내용인걸로 보입니다.

위 오류 로그의 13Line에 보면 PooledConnection.java:264 여기가 오류 발생원인 마지막 출처이죠. 


그래서 해당 소스를 찾아보았더니 PooledConnection.java:264 에 해당하는 Line이 아래 소스의 12Line 입니다.

 if (log.isDebugEnabled()) {  이 부분 입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;    
 
public class PooledConnection {
 
...
 
    protected void connectUsingDriver() throws SQLException {
 
        try {
            if (driver==null) {
                if (log.isDebugEnabled()) {
                    log.debug("Instantiating driver using class: "+poolProperties.getDriverClassName()+" [url="+poolProperties.getUrl()+"]");
                }
                ...


그래서 org.apache.juli.logging.Log 를 찾아가 보았더니 그냥 Interface 이더군요. 

위의 maven dependency 에 tomcat-jdbc 나 그에 속해있는 tomcat-juli에는 해당 인터페이스의 구현체가 전혀 없더군요. OTL


tomcat-jdbc 혼자서 사용할 수 없는 거라면 tomcat-juli 처럼 필요한 dependency를 걸어 놓아야 하는거 아닙니까?

(뭐 Debug Level 안 돌리면 문제가 없을지는 모르겠지만)


그래서 구현체가 어디있는지 찾아보았더니 tomcat-embed-core에 있더군요. 

로그 구현체는 core 에 있고 인터페이스는 jdbc에 있고 이거 뭔가 좀 바뀐것 같지 않나요?

1
2
3
4
5
    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-core</artifactId>
        <scope>provided</scope>
    </dependency


이건 tomcat-embed-core에 있는 구현체 입니다.

1
2
3
4
5
6
package org.apache.juli.logging;
 
/**
 * Hardcoded java.util.logging commons-logging implementation.
 */
class DirectJDKLog implements Log {        



이러한 뭔가 앞뒤 안맞는 tomcat-jdbc 를 보고 심하게 짜증이 일어나서 tomcat-jdbc 를 버리고 Hikari 로 갈아타 버렸습니다.

그래서 SpringBoot 2.0 부터는Default CP를 tomcat-jdbc에서 Hikari로 변경 하게 되었구나. 하고 혼자만의 이유로 막 수긍한 날 이었습니다.

반응형
반응형

HttpClient가 필요할 때 Spring에서 제공하는 RestTemplate 을 주로 사용합니다.

그런데 연동해야하는 서버가 EUC-KR Encoding 만 지원하는 경우가 심심치 않게 있습니다.


이럴 때 파라미터를 EUC-KR 로 Encoding 해서 보내야하는데 RestTemplate 로 EUC-KR Encoding 을 못해 고생한 경험이 있어서 그 방법을 공유해 봅니다.



아래 코드를 기준으로 설명 드리겠습니다.


Case1 은 잘못된 Encoding 입니다.

Case2,3 은 정상입니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLEncoder;
 
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.DefaultUriTemplateHandler;
 
public class Test {
 
  // RestTemplate을 이용해 EUC-KR 인코딩으로 요청 보내기
  public static void main(String[] args) throws UnsupportedEncodingException {
    String url = "http://google.com?q=" + URLEncoder.encode("테스트""EUC-KR");
    RestTemplate restOperations = new RestTemplate();
 
    // Case 1
    restOperations.getForObject(url, String.class);
 
    // Case2
    restOperations.getForObject(URI.create(url), String.class);
 
    // Case3
    DefaultUriTemplateHandler uriTemplateHandler = (DefaultUriTemplateHandler) restOperations.getUriTemplateHandler();
    uriTemplateHandler.setStrictEncoding(true);
    restOperations.getForObject(url, String.class);
  }
}



Case1

- RestTemplate 은 기본적으로 org.springframework.web.util.DefaultUriTemplateHandler 을 사용해서 String url을 자동으로 Encoding 합니다.

- 그런데 DefaultUriTemplateHandler 는 "UTF-8" 로 Encoding 이 Hard coding 되어 있어서 변경이 불가합니다.

- 그래서 Case1의 경우는 12 Line에서 EUC-KR로 encoding한 문자열을 자동으로 UTF-8로 다시 한번 Encoding 합니다.


Created GET request for "http://google.com?q=%25C5%25D7%25BD%25BA%25C6%25AE"


Case2

- String url로 넘기지않고 URI 객체를 넘기면 자동으로 Encoding 을 하지 않기 때문에 정상 동작합니다.


Created GET request for "http://google.com?q=%C5%D7%BD%BA%C6%AE"


Case3

- String url로 넘기더라도 DefaultUriTemplateHandler 의 설정에서 setStrictEncoding 을 true로 설정하면 자동으로 Encoding을 하지 않기 때문에 정상 동작합니다.


Created GET request for "http://google.com?q=%C5%D7%BD%BA%C6%AE"



** 참고.


Spring RestTemplate Encoding 이라고 Googling을 하면 org.springframework.http.converter.StringHttpMessageConverter 이 많이 출현하는데 이 녀석 때문에 삽질을 많이 했죠. 무식이 죄 ㅜㅜ.

StringHttpMessageConverter 는 Request가 아닌 Response의 Encoding을 처리한다고 보시면 됩니다.


반응형
반응형

Spring boot 실행할 때 args 를 전달해서 사용하는 방법입니다.

Spring boot에서  org.springframework.boot.ApplicationArguments 를 제공하고 있어서 Bean으로 받아서 사용하면 간단하게 쓸 수 있습니다.


1. getSourceArgs

 - 입력한 args 그대로 배열로 받아 옵니다.


2. getOptionNames

 - args 앞에 "--" 를 붙이면 옵션으로 인식 합니다. 옵션 args 사용 형식 --NAME=VALUE 

 - "--fruit=apple" 이렇게 args를 사용하면

 - getOptionName는 fruit 처럼 option name 들의 배열을 받아 옵니다.


3. getNonOptionArgs

- "--" 가 없는 경우 NonOption으로 인식합니다.

- "--" 가 없는 args 들의 값들을 받다 옵니다.


설명보다 아래 sample code를 보시는게 이해가 빠를 것 같습니다.

 


DemoApplication.java

1
2
3
4
5
6
7
8
9
10
11
12
package com.example.demo;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
 
@SpringBootApplication
public class DemoApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}


Test.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package com.example.demo;
 
import java.util.List;
import java.util.Set;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
 
@Component
public class Test implements ApplicationListener<ContextRefreshedEvent> {
  @Autowired
  private ApplicationArguments applicationArguments;
 
  @Override
  public void onApplicationEvent(ContextRefreshedEvent event) {
    String[] sourceArgs = applicationArguments.getSourceArgs();
    List<String> nonOptionArgs = applicationArguments.getNonOptionArgs();
    Set<String> optionNames = applicationArguments.getOptionNames();
 
    System.out.println("---원본 args---");
    for (String sourceArg : sourceArgs) {
      System.out.println(sourceArg);
    }
    System.out.println("---옵션아닌 args---");
    for (String nonOptionArg : nonOptionArgs) {
      System.out.println(nonOptionArg);
    }
    System.out.println("---옵션 args---");
    for (String optionName : optionNames) {
      List<String> optionValues = applicationArguments.getOptionValues(optionName);
      for (String optionValue : optionValues) {
        System.out.println(optionName + ":" + optionValue);
      }
    }
  }
 
}



Execute

 $JAVA_HOME/bin/java -jar demo.jar HI --MY_NAME=GONI --YOUR_NAME=GUEST --my.hobby=영화 --my.hobby=독서

* option args 에서 name 을 같게 해서 여러번 써서 List로 받을 수 있습니다.


Result

---원본 args---
--spring.output.ansi.enabled=always
HI
--MY_NAME=GONI
--YOUR_NAME=GUEST
--my.hobby=영화
--my.hobby=독서
---옵션아닌 args---
HI
---옵션 args---
spring.output.ansi.enabled:always
MY_NAME:GONI
YOUR_NAME:GUEST
my.hobby:영화
my.hobby:독서


반응형
반응형

 

Java Code

 

 

Result

 

 

 

Html and Javascript code

 
 

Result

 

---------------------------------

공개키 / 개인키 문자열로 처리.

반응형

'스크립트' 카테고리의 다른 글

jquery self unwrap  (0) 2018.11.06
jquery 확장 enter key function  (0) 2018.11.05
javascript cookie getCookie setCookie  (0) 2018.11.05
netstat unique ip  (0) 2018.09.10
aes256 cbc javascript and java  (0) 2018.08.09
ajax multiple parameter request list  (0) 2018.07.24
javascript object size  (0) 2018.07.23
jquery ajax ie no transport error  (0) 2018.07.17
반응형

Java 1.7 부터  java.nio.file.Files 를 통해서 File 의 생성날짜, 마지막 접근 날짜, 마지막 수정 날짜를 조회할 수 있습니다.


Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.attribute.BasicFileAttributes;
 
public class Test {
  public static void main(String[] args) throws IOException {
    File file = new File("/test/logs/debug.log");
    if (file.isFile()) {
      BasicFileAttributes readAttributes = Files.readAttributes(file.toPath(), BasicFileAttributes.class);
      System.out.println(readAttributes.creationTime().toMillis());
      System.out.println(readAttributes.lastAccessTime().toMillis());
      System.out.println(readAttributes.lastModifiedTime().toMillis());
    }
  }
}


Result

1
2
3
1511861243970
1511920327380
1511920793902



* 참고

linux 환경에서는 운용해본 결과 creationTime == lastModifiedTime 값이 같고 lastAccessTime 값이 변하지 않는 가장 과거의 값이었습니다.


* 결론

파일 생성시간을 가져오는 건 불가능해 보입니다. ㅜㅜ


반응형
반응형

Spring boot + Mybatis 로 프로젝트를 진행하고 있었습니다.

그런데 잘 되던 녀석이 갑자기 Exception이 나면서 구동이 안되는 겁니다.

ClassNotFound 라니 정말 당황했습니다. ㄷㄷㄷ


환경(Environment)

pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.4.2.RELEASE</version>
    <relativePath /<!-- lookup parent from repository -->
  </parent>
 
 
<dependencies>
...
    <!-- mybaits -->
    <dependency>
      <groupId>org.mybatis.spring.boot</groupId>
      <artifactId>mybatis-spring-boot-starter</artifactId>
      <version>1.2.1</version>
    </dependency>
...
</dependencies>


mybatis/config.xml

1
2
3
4
  <typeAliases>
    <package name="kr.co.tistory.goni9071.dao" />
    <package name="kr.co.tistory.goni9071.entity" />
  </typeAliases>



문제(Problem)

1. Mybatis 설정에서 TypeAliases의 package 를 이용하면 Entity 파일을 인식하지 못함.

2. 더 당황스러운 건 STS 개발환경에서는 문제가 없으나  executable jar/war 에서만 오류가 발생.


Exception

1
2
3
4
5
6
7
8
9
10
$ java -jar target/xxxx.jar
...
        at org.apache.ibatis.builder.xml.XMLMapperBuilder.configurationElement(XMLMapperBuilder.java:118)
        ... 44 more
Caused by: org.apache.ibatis.type.TypeException: Could not resolve type alias 'Message'.  Cause: java.lang.ClassNotFoundException: Cannot find class: Message
        at org.apache.ibatis.type.TypeAliasRegistry.resolveAlias(TypeAliasRegistry.java:120)
        at org.apache.ibatis.builder.BaseBuilder.resolveAlias(BaseBuilder.java:149)
        at org.apache.ibatis.builder.BaseBuilder.resolveClass(BaseBuilder.java:116)
        ... 48 more
...



원인(Cause)

1. application.properties 에서 아래와 같이 설정시에는 문제가 없음.

1
2
#mybatis
mybatis.config-location=classpath:mybatis/config.xml


2.  그러나 아래처럼 Java Config를 이용해 수동으로 설정시 오류가 발생.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Configuration
@MapperScan(value = Constants.PACKAGE_BASE + ".dao", sqlSessionFactoryRef = "coreSqlSessionFactory")
public class CoreRepositoryConfig {
 
  @Bean(name = "coreSqlSessionFactory")
  @Primary
  public SqlSessionFactory coreSqlSessionFactory(@Qualifier("coreDatasource") DataSource coreDatasource,
      ApplicationContext applicationContext) throws Exception {
    SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
    sqlSessionFactoryBean.setDataSource(coreDatasource);
    sqlSessionFactoryBean.setConfigLocation(applicationContext.getResource("classpath:mybatis/config.xml"));
    // 문제의 주범 및 해결책
    sqlSessionFactoryBean.setVfs(SpringBootVFS.class); 
    //
    return sqlSessionFactoryBean.getObject();
  }
}



해결책(Solution)

1. 위의 코드처럼 아래 한줄이 추가되면 문제 해결.

1
sqlSessionFactoryBean.setVfs(SpringBootVFS.class); 




반응형
반응형

AES256 CBC NoPadding UTF-8

 

Javascript Code

 

 

Result

 

 

Java Code

 

 

Result

 

 

 

* trim을 주의하세요.

CBC NoPadding 으로 16바이트 단위를 맞춰야해서 원래 문자열 뒤에 공백으로 16바이트 단위를 맞추고 복호화 할때 다시 그 공백을 trim으로 제거합니다.

원래 문자열 뒤에 공백이 있었다면 그 공백은 제거됩니다.

 

반응형

'스크립트' 카테고리의 다른 글

jquery 확장 enter key function  (0) 2018.11.05
javascript cookie getCookie setCookie  (0) 2018.11.05
netstat unique ip  (0) 2018.09.10
javascript java rsa  (0) 2018.08.13
ajax multiple parameter request list  (0) 2018.07.24
javascript object size  (0) 2018.07.23
jquery ajax ie no transport error  (0) 2018.07.17
윈도우 netstat grep wc 포트 커넥션 확인  (0) 2018.07.09
반응형

mybatis 사용중에 5000건 정도를 조회해서 화면에 표현해야하는 업무가 있었습니다.


툴에서 조회시에는 0.5 초 정도 걸리는데 웹상에서 jdbc를 통해 조회를하면 10초를 넘기는 상황이 발생했습니다.


구글링을 통해 찾아보니 mybatis에 fetchSize라는 옵션이 있더군요. 아래 처럼 추가했더니 0.5 초 이하로 속도가 나옵니다. @.@


1
<select id="selectListByDate" resultMap="logRM" fetchSize="1000">



fetchSize 어떻게 작동하길래 이렇게 속도가 빨라지나 찾아보았습니다.


설정하지 않으면 기본 값은 10 이라고 합니다.


fetchSize 가 10 이면 5000건을 조회하면 실제 db에서 500번을 조회하게 되는 겁니다.


fetchSize 가 1000 이면 5번이면 되는 겁니다.


이해하기 쉽게 예를 들면 같은 결과 값을 조회하는데 쿼리를 500번 날려서 받는 것과 5번만 날려서 받는 것 중에 어떤게 빠를까요?

반응형
반응형

2018/01/29 - [java] - java poi excel write 엑셀 쓰기

 

위 글에서 poi를 이용해 excel write 를 예제를 공유했었습니다.

 

그런데 데이터가 좀 많아지니 "gc overhead limit exceeded" 요런 Out Of Memory 오류가 발생합니다.

 

-Xmx 옵션을 통해서 Heap memory 를 늘리는 것도 한계가 있습니다.

 

이런 경우 해결책으로 org.apache.poi.xssf.usermodel.XSSFWorkbook 대신  org.apache.poi.xssf.streaming.SXSSFWorkbook 를 사용할 수 있습니다.

 

아래 코드를 참조하세요. SXSSFWorkbook 를 사용하면 지정한 row 개수 단위로 끊어서 flush 할 수 있습니다.

 

 

테스트 코드 입니다. 

java vm option을 -Xmx60m 정도 설정하고 SXSSFWorkbook 와 XSSFWorkbook 를 번갈아서 테스트하면 맨 아래 오류 코드를 확인할 수 있습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
 
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Font;
 
public class ExcelUtilTest {
  public static void main(String[] args) throws IOException, InvalidFormatException {
    ExcelUtil excel = new ExcelUtil("시트이름"100); // SXSSFWorkbook
    //ExcelUtil excel = new ExcelUtil("시트이름"); // XSSFWorkbook
    excel.setOffset(11);
    List<String> header = Arrays.asList("번호""이름""제목""기간""기타");
    excel.addRow("f8f8f8", Font.BOLDWEIGHT_BOLD, header);
    for (int i = 0; i < 10000; i++) {
      List<String> body = Arrays.asList(String.valueOf(i), "홍길동""제목입니다.""기간입니다.""기타");
      excel.addRow(body);
      excel.addRow(body);
      excel.addRow(body);
    }
    FileOutputStream fos = new FileOutputStream("/test/엑셀테스트1.xlsx");
    excel.write(fos);
 
  }
}
 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
    at org.apache.xmlbeans.impl.store.Saver$SynthNamespaceSaver.<init>(Saver.java:883)
    at org.apache.xmlbeans.impl.store.Saver.<init>(Saver.java:121)
    at org.apache.xmlbeans.impl.store.Saver$TextSaver.<init>(Saver.java:916)
    at org.apache.xmlbeans.impl.store.Cursor._xmlText(Cursor.java:546)
    at org.apache.xmlbeans.impl.store.Cursor.xmlText(Cursor.java:2436)
    at org.apache.xmlbeans.impl.values.XmlObjectBase.xmlText(XmlObjectBase.java:1500)
    at org.apache.poi.xssf.model.SharedStringsTable.getKey(SharedStringsTable.java:134)
    at org.apache.poi.xssf.model.SharedStringsTable.addEntry(SharedStringsTable.java:180)
    at org.apache.poi.xssf.usermodel.XSSFCell.setCellType(XSSFCell.java:797)
    at org.apache.poi.xssf.usermodel.XSSFRow.createCell(XSSFRow.java:176)
    at org.apache.poi.xssf.usermodel.XSSFRow.createCell(XSSFRow.java:37)
    at kr.go.seoul.scc.admin.web.util.ExcelUtil.addRow(ExcelUtil.java:117)
    at kr.go.seoul.scc.admin.web.util.ExcelUtil.addRow(ExcelUtil.java:77)
    at kr.go.seoul.scc.admin.web.util.ExcelUtilTest.main(ExcelUtilTest.java:21)
 
반응형

+ Recent posts