AbstractJExcelView에서 Template을 사용하는 것에 질문이 있습니다..

766 views
Skip to first unread message

Jin Kim

unread,
Oct 21, 2012, 7:12:49 PM10/21/12
to ks...@googlegroups.com
이것저것 찾아보고 있는데, AbstractJExcelVIew에 대한 설명은 꽤 있는데, Template을 사용하는 법에 대해서는 잘 나와있는 것이 없어서..이렇게 질문드립니다.
우선 AbstractJExcelView을 이용해서 WritableWorbook을 생성하고, Sheet를 생성해서, 거기에 값을 입력해서 넘기는 것 까지는 잘 됩니다.
그런데 기존에 있던 Template을 복사하여서, 그 복사된 Workbook에서 특정 값만 바꿔서 내보내는 작업을 수행하려고 하는데,
getTemplateSource를 사용하는 법을 모르겠습니다..
 
API를 찾아보니 url을 설정하면 될 것 같아서..생성자로 url을 설정하도록 생성해 봤습니다.
 
@RequestMapping(value="/make_doc", method=RequestMethod.GET)
 public View make_Document(Model model){
  System.out.println("Inside Make_Document");
  //save_data = input;
    
  return new TestJExcelView("/resources/Output");
 }
 
그랬더니 url이 정확하지 않다는 오류가 나는 것 같습니다. getTemplateSource를 실행하는 쪽에서 자꾸 에러가 발생을 하네요..
 
url의 정의를 살펴보니..
 * <p>Properties:
 * <ul>
 * <li>url (optional): The url of an existing Excel document to pick as a
 * starting point. It is done without localization part nor the .xls extension.
 * </ul>
 *
 * <p>The file will be searched with locations in the following order:
 * <ul>
 * <li>[url]_[language]_[country].xls
 * <li>[url]_[language].xls
 * <li>[url].xls
 * </ul>
이렇게 나와있는데..
여기서 It is done without localization part nor the .xls extension이라는 의미가 뭔지도 잘 모르겠습니다..
Template파일을
STS의 Spring MVC 트리구조상의
/프로젝트명/src/main/webapp/resources/Output.xls 에 카피하고
url을 /resource/Output 이라고 셋팅했는데..
잘못된 부분이 있으면 알려주시면 감사하겠습니다.
 

 

코바(이수홍)

unread,
Oct 21, 2012, 9:06:03 PM10/21/12
to ks...@googlegroups.com
url 기술 하는 부분에서 직접 file: prefix 한번 줘보세요 

앞에 prefix가 없으면 ApplicationContext에 따라가기 때문에 강제로 한번 줘보세요

ex : "/resources/Output" -> "file:/resources/Output" 이렇게 말이죠 

2012년 10월 22일 월요일 오전 8시 12분 49초 UTC+9, Jin Kim 님의 말:
Message has been deleted

Jin Kim

unread,
Oct 22, 2012, 12:35:53 AM10/22/12
to ks...@googlegroups.com
 
말씀해주신대로 해봤는데 같은 에러가 나는 것 같습니다.
에러코드를 적어봅니다.
 
심각: Servlet.service() for servlet [appServlet] in context with path [/Project] threw exception [Request processing failed; nested exception is java.lang.IllegalStateException: ApplicationObjectSupport instance [com.Project.inputview.TestJExcelView: unnamed] does not run in an ApplicationContext] with root cause
java.lang.IllegalStateException: ApplicationObjectSupport instance [com.Project.inputview.TestJExcelView: unnamed] does not run in an ApplicationContext
 at org.springframework.context.support.ApplicationObjectSupport.getApplicationContext(ApplicationObjectSupport.java:140)
 at org.springframework.web.servlet.view.document.AbstractJExcelView.getTemplateSource(AbstractJExcelView.java:156)
 at org.springframework.web.servlet.view.document.AbstractJExcelView.renderMergedOutputModel(AbstractJExcelView.java:130)
 at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:262)
 at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1157)
 at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:927)
 at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:827)
 at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
 at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
 at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:225)
 at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
 at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
 at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
 at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
 at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
 at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
 at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
 at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1001)
 at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579)
 at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:1770)
 at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
 at java.lang.Thread.run(Thread.java:662)

코바(이수홍)

unread,
Oct 22, 2012, 1:51:25 AM10/22/12
to ks...@googlegroups.com
STS의 Spring MVC 트리구조상의
/프로젝트명/src/main/webapp/resources/Output.xls 에 카피하고
url을 /resource/Output 이라고 셋팅했는데..

원글에 이런 문장이 있는데 잘 보면 /resource 뒤에 s가 빠져있는게 보이네요

이게 오타인지 프로그램에서도 그렇게 했는지 

궁금하네요 

2012년 10월 22일 월요일 오후 1시 35분 53초 UTC+9, Jin Kim 님의 말:

Jin Kim

unread,
Oct 22, 2012, 2:25:28 AM10/22/12
to ks...@googlegroups.com
코바는 답글 감사드립니다.
타이포 문제는 포스팅할때 잘못한것 같네요.. 프로그램 내에서는 /resources/라고 적었습니다.
상대경로 말고, 파일위치상의 절대경로도 테스트 해봤는데..안먹히네요..
"file:d/Output"도 테스트 해봤는데 작동이 안됩니다...
 
@Override
 protected final void renderMergedOutputModel(
   Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
  
  // Set the content type and get the output stream.
  response.setContentType(getContentType());
  OutputStream out = response.getOutputStream();
  WritableWorkbook workbook;
  if (this.url != null) {
   Workbook template = getTemplateSource(this.url, request);
   workbook = Workbook.createWorkbook(out, template);
  }
  else {
   logger.debug("Creating Excel Workbook from scratch");
   workbook = Workbook.createWorkbook(out);
  }
  buildExcelDocument(model, workbook, request, response);
  // Should we set the content length here?
  // response.setContentLength(workbook.getBytes().length);
  workbook.write();
  out.flush();
  workbook.close();
 }
 
AbstractJExcelView class안의 getTemplateSource에서 호출이 저런식으로 이루지는데..
getTemplateSource안에서는
 
protected Workbook getTemplateSource(String url, HttpServletRequest request) throws Exception {
  LocalizedResourceHelper helper = new LocalizedResourceHelper(getApplicationContext());
  Locale userLocale = RequestContextUtils.getLocale(request);
  Resource inputFile = helper.findLocalizedResource(url, EXTENSION, userLocale);
  // Create the Excel document from the source.
  if (logger.isDebugEnabled()) {
   logger.debug("Loading Excel workbook from " + inputFile);
  }
  return Workbook.getWorkbook(inputFile.getInputStream());
 }
 
이런작업이 이루어지네요..상대경로가 맞으면 인식이 되어야 할 것 같은데..잘 모르겠습니다.

이수홍

unread,
Oct 22, 2012, 2:30:11 AM10/22/12
to ks...@googlegroups.com
확장자도 같이 적어보세요

나의 iPhone에서 보냄

2012. 10. 22. 오후 3:25 Jin Kim <justt...@gmail.com> 작성:

--
Google 그룹스 'Korea Spring User Group' 그룹에 가입했으므로 본 메일이 전송되었습니다.
웹에서 이 토론을 보려면 https://groups.google.com/d/msg/ksug/-/CRoYzZltgKMJ을(를) 방문하세요.
이 그룹에 게시하려면 ks...@googlegroups.com(으)로 이메일을 보내세요.
그룹에서 탈퇴하려면 ksug+uns...@googlegroups.com로 이메일을 보내주세요.
더 많은 옵션을 보려면 http://groups.google.com/group/ksug?hl=ko에서 그룹을 방문하세요.

Jin Kim

unread,
Oct 22, 2012, 2:40:46 AM10/22/12
to ks...@googlegroups.com
확장자를 url에 같이 적어보라는 말씀이시죠??
그렇게 해봤는데, 같은 오류가 납니다..
음..url문제가 아닌걸까요...

김병철

unread,
Oct 22, 2012, 2:50:22 AM10/22/12
to ks...@googlegroups.com
제가 보기엔

원본 소스 : 
@RequestMapping(value="/make_doc", method=RequestMethod.GET)
 public View make_Document(Model model){
  System.out.println("Inside Make_Document");
  //save_data = input;
    
  return new TestJExcelView("/resources/Output");
 }
에서 "/resources/Output"에서 첫 "/"을 제거하시고, resources/Output을 하세요.

View 소스 : 
AbstractJExcelView class안의 getTemplateSource에서 호출이 저런식으로 이루지는데..
getTemplateSource안에서는
 
protected Workbook getTemplateSource(String url, HttpServletRequest request) throws Exception {
  LocalizedResourceHelper helper = new LocalizedResourceHelper(getApplicationContext());
  Locale userLocale = RequestContextUtils.getLocale(request);
  Resource inputFile = helper.findLocalizedResource(url, EXTENSION, userLocale);
  // Create the Excel document from the source.
  if (logger.isDebugEnabled()) {
   logger.debug("Loading Excel workbook from " + inputFile);
  }
  return Workbook.getWorkbook(inputFile.getInputStream());
 }

에서
getApplicationContext()을 하면 아마도 "/"을 가지고 있을 듯 합니다.

웹 설정 중에 org.springframework.web.servlet.DispatcherServlet를 매핑해서 처리 하는 부분이 있을 것 같은데요. 거기에 url-pattern 있고, /으로 설정 되어 있을 거 같습니다.


2012년 10월 22일 오후 3:30, 이수홍 <sbc...@gmail.com>님의 말:



--
"올바른 성장과 따뜻한 나눔"
------------------------------------------------------------------------------------------------------------------
넥스트리소프트(주)  SI사업부 개발2팀 김병철
서울 금천구 가산동 371-28 우림라이온스밸리 A동 405호
M. 010-2809-0928


Jin Kim

unread,
Oct 22, 2012, 3:16:59 AM10/22/12
to ks...@googlegroups.com
 
테스트 해봤는데 안되네요..
'/' 문제라고 하기엔, 절대경로를 입력하거나 d:/output으로 입력했을때 작동을 했어야 하지 않았을까 생각이 듭니다.
 
workbook이 자동으로 입력되어 들어오다보니, 템플렛을 쓰는 다른 방법들을 고민해봤는데 딱히 좋은 방법이 없는 것 같습니다.
JXL 자체도 조금 불완전한 면이 많은것 같네요..
흠..POI로 가야하나 고민중입니다..

코바(이수홍)

unread,
Oct 22, 2012, 4:17:27 AM10/22/12
to ks...@googlegroups.com
혹시 런타임이 아니라 서버 시작시에 에러가 발생하나요??

2012년 10월 22일 월요일 오후 4시 16분 59초 UTC+9, Jin Kim 님의 말:

Jin Kim

unread,
Oct 22, 2012, 5:43:03 AM10/22/12
to ks...@googlegroups.com
윽..글을 길게 썼는데 날라갔습니다..
코바님과 병철님 모두 답변 감사드립니다.
 
우선 서버 시작시에 에러나는 것은 아닙니다. 서버는 문제없이 정상적으로 작동합니다.
프로젝트에서는 Restful방식을 사용하고 있는데, 화면단에서 /rest/save/make_doc 이라는 Uri를 디스패치 서블렛이 받으면 그에 맞는 컨트롤러가
위의 클래스를 실행시켜서 JExcelView를 리턴시키는 방식을 사용하고 있습니다.
 
시험용으로 Url셋팅없이 빈 Workbook을 생성하여 Sheet를 만들고 값을 몇개 입력해보니 문제없이 정상적으로 작동합니다.
문제는 템플릿을 이용하기 위해 Url를 셋팅하려고 할때 발생합니다.
 
템플릿용 파일은 Java Application 테스트 프로그램을 작성하여 테스트 해본 결과 이상없이 작동합니다.
 
Url을 설정하는 방법은 두가지를 테스트 해보았습니다.
첫번째는 위와 같이 생성자를 사용하는 방법이고,
두번째는 TestJExcelView클래스 안의 buildExcelDocument(Map<String, Object> model, WritableWorkbook workbook, HttpServletRequest request,   HttpServletResponse response) 함수 내부에 getTemplateSource를 사용하는 방법이었습니다.
두방법 모두 비슷한 에러를 냅니다.
 
템플릿안의 형식이 매우 중요해서 그냥 생성할 수도 없는 상황이라..조금은 난감합니다.
Url를 어떻게 입력해야 하는지 잘 감이 안옵니다.
혹시 다른 문제가 아닐까 좀더 고민해 보겠습니다. 

코바(이수홍)

unread,
Oct 22, 2012, 5:57:14 AM10/22/12
to ks...@googlegroups.com
원인을 알았습니다.

new TestJExcelView("/resources/Output");

이렇게 한부분에서 객체를 직접 생성 시키는데 

내부에서 보니 ApplicationContext를 가져오는 곳이 있네요

직접 객체를 실행시키면 당연히 ApplicationContext을 못가져오니 에러가 발생하고 있네요

그래서 해결방법은 그 객체를 직접 bean으로 등록 시켜 주입시켜 사용하는 방법과 

아니면 setApplicationContext 메소드에 직접 applicationContexte를 받아서 넣어주는 방법이 있겠네요

아마 정확히 이문제 이네요

경로 문제가 아니라 

그 이후 경로 테스트를 하셔야 겠네요 


2012년 10월 22일 월요일 오후 6시 43분 3초 UTC+9, Jin Kim 님의 말:

Jin Kim

unread,
Oct 22, 2012, 7:22:36 AM10/22/12
to ks...@googlegroups.com
오 에러 첫부분에서 ApplicationContext문제라고 나온것이 그런 문제였던 것인가요..
내일 다시한번 테스트 해보겠습니다. 감사합니다. :)

윤재진

unread,
Oct 22, 2012, 11:22:19 AM10/22/12
to ks...@googlegroups.com
TestJExcelView는 어떻게 작성을 하신건가요??

TestJExcelView를 봐야지 좀 더 알 수 있을꺼 같은데요. ^^;;

제가 했던 방법을 공유해봅니다.

전 templeteSource는 안쓰고 제가 만들었는데요.


spring mvc+ poi+ jxls 입니다.

2012년 10월 22일 오후 8:22, Jin Kim <justt...@gmail.com>님의 말:
웹에서 이 토론을 보려면 https://groups.google.com/d/msg/ksug/-/CiIqybX_DRgJ을(를) 방문하세요.

이 그룹에 게시하려면 ks...@googlegroups.com(으)로 이메일을 보내세요.
그룹에서 탈퇴하려면 ksug+uns...@googlegroups.com로 이메일을 보내주세요.
더 많은 옵션을 보려면 http://groups.google.com/group/ksug?hl=ko에서 그룹을 방문하세요.



--
========================================
블로그 : http://spyrogira256.blogspot.com
             http://spyrogira256.blog.me
윤재진 spyrog...@gmail.com
Google Talk. spyrogira256@gmail.com
NateOn. anjff...@lycos.co.kr
Mobile. 010-9747-8761
========================================

Jin Kim

unread,
Oct 22, 2012, 7:40:33 PM10/22/12
to ks...@googlegroups.com
재진님 답변 감사드립니다. :) 검색하다가 같은 블로그를 찾아서 봤던 것 같아요..보니까 저는 엄두가 안나는 방법이던데..대단하십니다!!
 
우선 결과를 말씀드리면, 코바님 말씀대로 ApplicationContext를 찾지 못해서 발생한 에러가 주였던 것 같습니다.
Context에 빈으로 설정하고, 프로퍼티에 url값을 설정해서 집어넣었더니..
깔끔하게 카피되어서 들어오네요!!
카피된 Workbook에 값을 바꿔서 화면으로 넘겨지는 것 까지 잘됩니다. 너무 깔끔하게 한번에 이뤄져서..
저도 깜짝 놀랐네요!!
Url Path는 병철님께서 말씀해주신 것 같이 '/'가 자동적으로 포함되어 있습니다. 그래서 '/'를 빼고 'resouces/Output'으로 넣으면 잘 찾아갑니다.
답변 주신분들 너무너무 감사드립니다!!
 
참고로 컨트롤러와 ApplicationContext의 설정을 공유합니다.
<bean id="excelDownload" class="com.project.inputview.TestJExcelView" p:url="resources/Output" scope="session"></bean>
 
위와 같이 프로퍼티로 url을 줄 수 있게 되어있습니다.
 
@RequestMapping(value="/make_doc", method=RequestMethod.GET)
 public String make_Document(Model model){
  System.out.println("Inside Make_Document");
     
  
  return "excelDownload";
 }
 
그리고 나선 이렇게 간단하게;;; 넘 간단하네요..
 
TestJExcelView는 그냥 일반적으로 똑같습니다. 기회가 되면 블로깅하도록 하겠습니다.
감사합니다.!!
윤재진 spyrog...@gmail.com
Google Talk. spyrogira256...@gmail.com
Reply all
Reply to author
Forward
0 new messages