2015년 2월 26일 목요일

hibernate + jpa + jta 사용할때 insert+update+delete 작동안되는 문제

거의 한달을 삽질하던 문제였다.

정말 우연치 않게 검색된 블로그에서 힌트를 얻어 수정...

http://kyungtaak.tistory.com/66
역시 메뉴얼이 답이다.

블로그 내용은 하이버네이트3 버전 일때 설정인것 같아서 최신 버전으로 올려본다.
톰캣을 사용해서 jta는 atomikos를 사용했다.

hibernate.transaction.manager_lookup_class 설정은 하이버네이트3버전에서 사용하는 설정인듯..
hibernate.transaction.jta.platform는 하이버네이트4에서 추가되었다.

아래는 상세 내용들..

properties.put("hibernate.transaction.factory_class", "org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory");
        //properties.put("hibernate.transaction.manager_lookup_class", "com.atomikos.icatch.jta.hibernate.TransactionManagerLookup");
        properties.put("hibernate.transaction.jta.platform", "com.atomikos.icatch.jta.hibernate4.AtomikosPlatform");
        properties.put("hibernate.transaction.flush_before_completion", "true");
        properties.put("hibernate.transaction.auto_close_session", "true");
        properties.put("hibernate.connection.release_mode", "auto");

2015년 1월 26일 월요일

스프링 xml 설정을 자바코드로 바꿀때 주의사항

<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
            <property name="cacheManager">
                <bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
                    <property name="configLocation" value="classpath:/kr/co/callmix/conf/cache/ehcache.xml"/>
                </bean>
            </property>
        </bean>
        <bean id="annotationCacheOperationSource" class="org.springframework.cache.annotation.AnnotationCacheOperationSource" />
        <bean id="cacheInterceptor" class="org.springframework.cache.interceptor.CacheInterceptor">
            <property name="cacheOperationSources" ref="annotationCacheOperationSource" />
            <property name="cacheManager" ref="cacheManager"/>
        </bean>
        <bean id="cacheAdvisor" class="org.springframework.cache.interceptor.BeanFactoryCacheOperationSourceAdvisor">
            <property name="cacheOperationSource" ref="annotationCacheOperationSource" />
            <property name="advice" ref="cacheInterceptor" />
        </bean>


이런 코드가 있었다.

자바코드로 다음과 같이 변경했다.

        EhCacheManagerFactoryBean ehCacheManagerFactoryBean = new EhCacheManagerFactoryBean();
        ehCacheManagerFactoryBean.setConfigLocation(new ClassPathResource("/kr/co/callmix/conf/cache/ehcache.xml"));
     
        EhCacheCacheManager cacheManager = new EhCacheCacheManager();
        cacheManager.setCacheManager(ehCacheManagerFactoryBean.getObject());

     
        AnnotationCacheOperationSource cacheOperationSource = new org.springframework.cache.annotation.AnnotationCacheOperationSource();
     
        CacheInterceptor cacheInterceptor = new CacheInterceptor();
        cacheInterceptor.setCacheOperationSources(cacheOperationSource);
        cacheInterceptor.setCacheManager(cacheManager);
     
        BeanFactoryCacheOperationSourceAdvisor cacheAdvisor = new BeanFactoryCacheOperationSourceAdvisor();
        cacheAdvisor.setCacheOperationSource(cacheOperationSource);
        cacheAdvisor.setAdvice(cacheInterceptor);

그런데 오류가 난다. 이래저래 바꿔봐도 오류가 났었다.
깊이 파보진 않았지만, 전체적으로 대중이 없어보였다.

단지 짐작으로 xml로 생성해주던 빈들을 자바코드로는 생성하지 않고,
전부 하나의 코드로 우겨넣어서 그런것 같았다.

기존에 생성했던 빈들을 다른 곳에서도 사용할수 있을거라 생각한것이다.
애초에 스프링에서 지원하는 클래스로 생성하는 것들이니 어찌보면 당연한걸지도 모른다.

그래서 다음과 같이 바꿔봤다.

@Bean
    public EhCacheManagerFactoryBean ehCacheManagerFactoryBean(){
     
        EhCacheManagerFactoryBean ehCacheManagerFactoryBean = new EhCacheManagerFactoryBean();
        ehCacheManagerFactoryBean.setConfigLocation(new ClassPathResource("/kr/co/callmix/conf/cache/ehcache.xml"));
     
        return ehCacheManagerFactoryBean;
    }
 
    @Bean
    public CacheManager cacheManager(){
        return new EhCacheCacheManager(ehCacheManagerFactoryBean().getObject());
    }
 
    @Bean
    public AnnotationCacheOperationSource cacheOperationSource(){
        return new org.springframework.cache.annotation.AnnotationCacheOperationSource();
    }
 
    @Bean
    public CacheInterceptor cacheInterceptor(){
     
        CacheInterceptor cacheInterceptor = new CacheInterceptor();
        cacheInterceptor.setCacheOperationSources(cacheOperationSource());
        cacheInterceptor.setCacheManager(cacheManager());
     
        return cacheInterceptor;
    }
 
    @Bean
    public BeanFactoryCacheOperationSourceAdvisor cacheAdvisor(){
     
        BeanFactoryCacheOperationSourceAdvisor cacheAdvisor = new BeanFactoryCacheOperationSourceAdvisor();
        cacheAdvisor.setCacheOperationSource(cacheOperationSource());
        cacheAdvisor.setAdvice(cacheInterceptor());
     
        return cacheAdvisor;
    }

왠걸...작동이 된다.

정확한 원인은 파악하지 못했지만, 짐작한게 맞는것 같다.
xml설정을 자바로 바꿀댄 최대한 쪼개주자.
그게 유지보수도 좋고 오류도 없는것 같다.

2014년 12월 12일 금요일

org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation


스프링 mvc에서 객체를 json로 반환하기 위해 
ResponseBody를 사용해서 객체를 반환했다.

그런데 제목과 같은 오류가 났다. 인터넷 온갖을 다 뒤져봐도 대답은 거의 비슷하다.
간혹 스프링 3.0버전의 버그때문이라는 분도 있었지만, 나는 해당사항이 아니였다.

<mvc:annotation-driven>
    <mvc:message-converters>
        <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"  />
    </mvc:message-converters>
</mvc:annotation-driven>

이것도 넣었다.

jackson 라이브러리도 다 넣었다.
근데 계속 에러가 난다.

미쳐버리겠다 ㅠㅠ

신기한건 어떤 url은 정상 작동하고 어떤 url은 정상작동을 안한다.
이클립스에서 디버깅을 해서 하나씩 찾아봤다.

너무 지쳐서 상세히 적지를 못하지만, 주절주절 적으면 오류은 이렇다.

스프링에서 ResponseBody로 반환할때 미디어 타입을 찾는데,
이때 스프링에서 주소의 확장자 까지 참고해서 찾게된다.

만약 확장자가 jpg나 cmx같이 반환할 미디어타입중 마땅한게 없으면
저런오류가 나는거다.

나같은 경우 주소 확장자를 cmx라고 했는데, 이놈이 이미지타입으로
지정되고 있던거다....

그래서 난 주소에 확장자를 모두 빼버렸다....
해보진 않았지만, 아마 ajax호출할때 데이터 반환타입을 application/json으로
하면 작동이 잘될지도 모르겠다....

2014년 10월 26일 일요일

mybatis 쿼리를 이쁘게 출력하기

mybatis로 개발하다보면 한가지 아쉬운 부분이 있다.

바로 쿼리로그!!



파라미터가 바인드되지 않고 물음표로 나오거나, 개행, 탭문자가 전부 무시되어서 가독성이 극악이기 때문이다.



그래서 많은 사람들이 크게 3가지 방법으로 개선을 시도한다.

1. mybatis 소스 자체를 고치거나

2. mybatis의 인터셉터 기능을 이용해서 로그로 찍힐 쿼리를 수정하거나

3. 별도의 라이브러리를 사용하는 방법이다.


3가지 전부 한계점이 있다.

1번은 메이븐 프로젝트와 같은 경우 수정된 mybatis를 배포하기 어려운점이 있다.
2번은 코드개발에 무척 많은 시간이 걸린다는 점.
3번은 보통 log4sql나 log4jdbc을 사용하는데 파라미터 바인드, 개행 탭무시등 둘중 하나가 제대로 되지 않는다.

나같은 경우 처음에는 log4sql을 사용했는데, log4sql은 메이븐에 배포 되지도 않고, System.out를 사용한다기에, log4jdbc로 교체했다.

그러나 log4jdbc는 개행, 탭문자가 전부 무시되어 불편함이 많았다.



현재 개발중인 프로젝트가 메이븐프로젝트이기 때문에 1번은 넘어가고, 2번 방법으로 시도를 해보았다.

별도로 내가 개발하진 않고, 인터넷이 공개되어 있는 소스를 가져다 사용했는데, 이것또한 한계점이 있었다.



파라미터 변수를 바인드 할때 #{params.param.value} 처럼 2단계로 매핑이 되어 있을 경우 에러가 났다.

이런케이스 까지 커버하려니 무척이나 귀찮았고, 이것말고도 다른 에러가 날수도 있기 때문에 바로 포기.



그 다음 시도한 방법은 log4jdbc를 수정하는 방법이다.(실제로 시도해보니 수정할 필요가 없는, 설정값 변경 방법이다.)

log4jdbc는 mybatis에서 던져준 쿼리를 사용하는게 아니라 jdbc드라이버를 이용해서 쿼리를 캡쳐하기 때문에 개행, 탭문자를 무시하는 부분만 찾아내면 될것 같았다.



Slf4jSpyLogDelegator클래스를 보면 processSql 메소드가 그러한 작업을 수행하는데,
분기 조건중에 DriverSpy.DumpSqlMaxLineLength가 0이하이면 해당 기능을 수행하지 않고, 바로 리턴한다.

그리고 DriverSpy.DumpSqlMaxLineLength값은 System.properties("log4jdbc.dump.sql.maxlinelength")에서 불러온다.

그래서 현재 톰캣을 사용중인 나는 톰캣에 -Dlog4jdbc.dump.sql.maxlinelength=0로 설정값을 주고 사용해 보니 잘 작동된다.

2014년 9월 23일 화요일

Unsupported major.minor version 51.0

Unsupported major.minor version 51.0

노트북에서 이클립스로 열심히 개발하고 첨으로 서버에 올리는데

저런 에러가 난다.


뭐지 처음 보는 에러..

구글신에서 물어보니 서버에 깔린 자바버전이 낮아서 그런거란다.

나는 1.7에서 개발하고 서버는 1.6이라네.


javac -version으로 확인해보니 서버는 1.7이다.

뭐지????????????


몇시간 삽질하다가 다시 확인해봤다.

java -version

버전인 1.6이래 ㅠㅠㅠㅠㅠㅠㅠ


버전확인 할때 javac, java 꼭 둘다 확인해 보자.

가상머신이랑 컴파일러가 서로 다를수 있다!!

2014년 9월 4일 목요일

이클립스 안드로이드 셋팅일때 svn 오류대처

머리털 나고 처음 앱 개발을 해야할 일있어서

svn깔고 이것저것 하다가 프로젝트 조차도 열리지 않는 에러가 갑자기 발생했다.

짐작하기론.. 현재 쓰는 이클립스가 케플러인데 svn은 루나버전에 맞춰나온

지나치게 새버전(?)이라서 그런것 같았다.

구글로 검색해보니 안드로이드 이클립스에서 svn 쓸때

이래저래 고생하는 사람들이 나 말고도 많은듯....


오류유형도 다양하고 대처방법도 너무 많고..


그러다가 그나마 비슷한 오류 중에 간단한 대처법이 있었다.

"프로젝트 클린"를 하면 된다. 이걸로 어느정도 오류 해결..

일단 프로젝트가 열린다.


하지만 엑박이 너무 많다.

프로젝트 프로퍼티에서 안드로이드 버전을 변경했다가

다시 되돌려 보았다. 된다. 요건 혼자 알아낸 방법 ㅋㅋ


삽질 끄읕...

2014년 7월 27일 일요일

무설치 java jre,jdk가 필요할때

이클립스 설치하면서 자바도 설치하려고 했는데

무슨일인지 자바설치가 되지 않는다. ㅠㅠ

자바는 꼭 설치할 필요는 없고, jre와 jdk만 경로로 지정해 주면 되기때문에

무설치 자바가 있는지 찾아봤지만 이것도 없다.


곰곰히 생각해보니까 전에 깔아뒀던 sql developer가 자바로 구동되는 건데

자바를 설치한적이 없다. 심지어 이것도 무설치다.


sql developer는 오라클에서 만든 오라클 DB관리 툴이다.

토드, 오렌지 같은건데 라이센스가 무료에다가 한글지원까지 되니 관심있으면

한번 써보시길...


아무튼... sql developer 폴더를 뒤져보니까 jdk폴더가 똭! ㅋㅋ 자바 1.7버전이다.

앗싸를 외치고 이클립스 폴더에 복사를 했다.

이클립스 실행하니까 jre폴더가 이클립스에 없다고 한다.

ini파일 수정하기 귀찮다. jre폴더를 옮기기로한다.

jdk폴더에 jre가 있다. 이걸 이클립스 폴더로 다시 옮긴다.

이클립스를 실행해본다. 실행 성공!! ㅋㅋ


자바를 설치안해서 그런지 왠지 내  피씨가 깨끗해진 기분이다.