Translate

2017년 11월 19일 일요일

[TypeScript] TS90010 Type A is not assignable to Type A 이슈





Framework: Angular 4


HTTP 요청에 파라미터를 추가하여 날리기 위해 URLSearchParams 에서 AppendAll 메소드를 사용하는데 아래와 같이 오류가 발생을 했다.
1004lucifer

1004lucifer

TS90010:Type 'URLSearchParams' is not assignable to type 'URLSearchParams'. Two different types with this name exist, but they are unrelated. Property 'rawParams' is missing in type 'URLSearchParams'.

(두개의 URLSearchParams 가 실은 같은 타입이 아니라는 이야기..)





지난번 기술한 이슈와 동일한 원인이며 해결방법 또한 동일하다.
(아래의 링크를 참조)

- [TypeScript] TS2345 Argument of type A is not assignable to parameter of type A 이슈


2017년 11월 16일 목요일

[Angular 2-4] Locale 사용 시 브라우저마다 DatePipe 결과가 다른 증상





환경: Angular 4



최근 다국어를 고려한 프로젝트를 제작중인데,
DatePipe 사용 시 의도하지 않은 결과가 나와서 혼란스럽다.



증상
1004lucifer
아래의 소스를 사용 시 브라우저마다 결과값이 다르게 나올 수가 있다.
(Module 에서 LOCALE_ID 지정시에만 증상 발생)

app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { LOCALE_ID, NgModule } from '@angular/core';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [
    { provide: LOCALE_ID, useValue: 'ko' }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }


app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  nowDate = new Date();
}

app.component.html
<h1>
  {{ nowDate | date:'yyyy-MM-dd HH:mm:ss'}}
</h1>






처음에 'yyyy-MM-dd HH:mm:ss' 패턴대로 나올꺼라고 생각했지만 결과는 아래와 같다.

Chrome v62.0.3202.89




Microsoft Edge 38.14393.0.0



1004lucifer

JSFiddle 에서는 아래와 같이 보여진다.
(이것역시 보는 브라우저에 따라 결과가 다르다.)







원인

왜그런지 한참을 찾았는데 원인은
Angular 4 버전까지 DatePipe에서 Browser의 i18n API 를 사용하기 때문이다.


현재 Angular 5 가 출시 되었으며 i18n 에서 다중 브라우저 불일치 버그로 인해 브라우저 API 를 사용하지 않고 Unicode Common Locale Data Repository (CLDR) 기반의 데이터를 자체적으로 가지고 있다고 한다.
https://github.com/angular/angular/blob/master/CHANGELOG.md#i18n-pipes

1004lucifer
Angular 5 가 나온 사실을 모르고 github의 한글 형식의 CLDR 소스(링크)를 보고 어디서 사용해서 자동으로 한글이 붙어서 나오는걸까 알아봤었고, Angular 사이트에서 본 DatePipe API 또한 Angular 5 버전 4버전이라 착각하며 보면서 한참을 삽질을 하고 있었다.

http://han41858.tistory.com/43
삽질을 하다가 위의 블로그의 Angular5 소식을 보고 바로 의문이 풀렸다.





해결방법

현재 상황으로는 아래의 우회방법 말고는 딱히 해결방법이 없어보인다.

아직 테스트 해보지는 못했으나 Angular 5 에서는 이슈가 해결되거나 Locale을 바꾸지 않는 정상적인 방법으로 해결이 가능하지 않을까 싶다.
(지금 쓰고있는 JHipster 가 아직 Angular 5지원을 안하는데 어쩌지?? ㅠㅠ)
1004lucifer
app.component.ts
import { Component } from '@angular/core';
import {DatePipe} from '@angular/common';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  nowDate = new Date();
  datePipe: DatePipe;
  constructor() {
    this.datePipe = new DatePipe('en-US');
  }
}


app.component.html
<h1>
  {{ datePipe.transform(nowDate, 'yyyy-MM-dd HH:mm:ss') }}
</h1>



JSFiddle



2017년 11월 14일 화요일

[CSS] 상속받은 상위 속성(style) 무효화(초기화) 하기





PS.
모든 상위속성을 무시하는 걸 원한다면 아래 링크의 라이브러리를 사용하기를 권장한다.
- 10+ Best CSS Reset Stylesheets





많은 상황에서 상속받은 CSS에 대하여
depth를 이용하거나 CSS우선순위를 이용하여 덮어쓰기(!?) 하여 해결이 가능한것 같다.


하지만 다른 style을 적용하지 않고 부모 엘리먼트의 style 상속을 받지 않아야 하는 경우가 발생하여 알아보니 :not(selector) 라는 기능이 있었다.
1004lucifer
엄밀히 말하면 상속을 초기화(reset) 한다기 보다..
부모 Element 에서 style 적용 시 특정 Element에 style이 적용되지 않도록 하는 기능이다.





예제

<div class="parent">
  <span>aaaaaa</span>< br/>
  <p>aaaaaa</p>< br/>
  <span>aaaaaa</span>< br/>
  <span>aaaaaa</span>
</div>
.parent :not(p) {
  color:red;
}
1004lucifer









아래와 같은 형식으로도 사용이 가능하니 의외로 활용성이 좀 있어 보인다.

- div :not(.home) {…}







- div *:not(p) em {…}







- input:not([type="text"]) {…}







- h2:not(.foo):not(.bar) {…}







- li:not(.pingback) .comment-content p:first-child:first-line {…}







- div:not(.home) h2 + p:first-letter {…}







- .post:not(.first-post) a:hover {…}





PS.
정보를 찾다보니 jQuery 도 :not() Selector 가 있다는걸 알았다.
https://api.jquery.com/not-selector/

무효, 리셋,


[혼잣말]
지금 알고있는걸 그때도 알았더라면..
상속받은 상위 속성을 무효화(무시) 할줄 몰라서 다시 style을 덮어쓰기 하며 힘들게 작업하던 스스로에게 안쓰러워진다..;;


[Angular 2+] Java의 ZonedDateTime 형식 Formatting





환경 - Angular 4



다국어 홈페이지를 제작하려다보니 DateTime 형식을
Java 8의 ZonedDateTime을 사용하게 되었다.


1004lucifer
아래와 같은 포멧을 사용한다. (ISO 8601)

- 2017-11-14T12:52:23+00:00
- 2017-11-14T12:52:23Z
- 20171114T125223Z



앵귤러에서 지원하는게 있을까 한참 찾다가 포멧을 직접 만들까 했는데
ES6 에서 기본 지원이 되고 있었다.






ES6에서 아래와 같이 사용 가능하다 (TypeScript 사용가능)
var today = new Date('05 October 2011 14:48 UTC');

console.log(today.toISOString()); // Returns 2011-10-05T14:48:00.000Z

1004lucifer

ES5의 JavaScript 에서는 아래와 같이 prototype 추가해서 사용 가능하다.
if (!Date.prototype.toISOString) {
  (function() {

    function pad(number) {
      if (number < 10) {
        return '0' + number;
      }
      return number;
    }

    Date.prototype.toISOString = function() {
      return this.getUTCFullYear() +
        '-' + pad(this.getUTCMonth() + 1) +
        '-' + pad(this.getUTCDate()) +
        'T' + pad(this.getUTCHours()) +
        ':' + pad(this.getUTCMinutes()) +
        ':' + pad(this.getUTCSeconds()) +
        '.' + (this.getUTCMilliseconds() / 1000).toFixed(3).slice(2, 5) +
        'Z';
    };

  }());
}




참고
- http://doohyun.tistory.com/55
- https://stackoverflow.com/questions/29297257/what-time-zone-does-the-javascript-new-date-use
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString

2017년 11월 13일 월요일

[MySQL][해결방법] Deadlock found when trying to get lock; try restarting transaction





환경
- MySQL v5.7
- Java (Spring-Boot)




증상

Java Spring 애플리케이션에서 아래와 같이 오류가 발생했다.
1004lucifer



2017-11-13 00:00:23.547 ERROR 19976 --- [TaskScheduler-1] o.s.s.s.TaskUtils$LoggingErrorHandler    : Unexpected error occurred in scheduled task.

org.springframework.dao.DeadlockLoserDataAccessException:
### Error updating database.  Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
### The error may involve [_PACKAGE_NAME_].[_CLASS_NAME_].[_METHOD_NAME_]-Inline
### The error occurred while setting parameters
### SQL: insert into ~~~~
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
; SQL []; Deadlock found when trying to get lock; try restarting transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
        at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:263) ~[spring-jdbc-4.3.7.RELEASE.jar:4.3.7.RELEASE]
        at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73) ~[spring-jdbc-4.3.7.RELEASE.jar:4.3.7.RELEASE]
        at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:73) ~[mybatis-spring-1.3.1.jar:1.3.1]
        at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:446) ~[mybatis-spring-1.3.1.jar:1.3.1]
        at com.sun.proxy.$Proxy254.insert(Unknown Source) ~[na:na]
        at org.mybatis.spring.SqlSessionTemplate.insert(SqlSessionTemplate.java:278) ~[mybatis-spring-1.3.1.jar:1.3.1]
        at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:57) ~[mybatis-3.4.4.jar:3.4.4]
        at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:59) ~[mybatis-3.4.4.jar:3.4.4]
        at com.sun.proxy.$Proxy259.[_METHOD_NAME_](Unknown Source) ~[na:na]
        at [_PACKAGE_NAME_].[_CLASS_NAME_].[_METHOD_NAME_]([_CLASS_NAME_].java:55) ~[classes/:na]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_151]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_151]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_151]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_151]
        at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:65) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
        at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_151]
        at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) [na:1.8.0_151]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_151]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) [na:1.8.0_151]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_151]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_151]
        at java.lang.Thread.run(Thread.java:748) [na:1.8.0_151]
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_151]
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_151]
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_151]
        at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_151]
        at com.mysql.jdbc.Util.handleNewInstance(Util.java:425) ~[mysql-connector-java-5.1.42.jar:5.1.42]
        at com.mysql.jdbc.Util.getInstance(Util.java:408) ~[mysql-connector-java-5.1.42.jar:5.1.42]
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:951) ~[mysql-connector-java-5.1.42.jar:5.1.42]
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3973) ~[mysql-connector-java-5.1.42.jar:5.1.42]
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3909) ~[mysql-connector-java-5.1.42.jar:5.1.42]
        at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2527) ~[mysql-connector-java-5.1.42.jar:5.1.42]
        at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2680) ~[mysql-connector-java-5.1.42.jar:5.1.42]
        at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2490) ~[mysql-connector-java-5.1.42.jar:5.1.42]
        at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1858) ~[mysql-connector-java-5.1.42.jar:5.1.42]
        at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:1197) ~[mysql-connector-java-5.1.42.jar:5.1.42]
        at org.apache.ibatis.executor.statement.PreparedStatementHandler.update(PreparedStatementHandler.java:46) ~[mybatis-3.4.4.jar:3.4.4]
        at org.apache.ibatis.executor.statement.RoutingStatementHandler.update(RoutingStatementHandler.java:74) ~[mybatis-3.4.4.jar:3.4.4]
        at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:50) ~[mybatis-3.4.4.jar:3.4.4]
        at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117) ~[mybatis-3.4.4.jar:3.4.4]
        at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:76) ~[mybatis-3.4.4.jar:3.4.4]
        at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:198) ~[mybatis-3.4.4.jar:3.4.4]
        at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:185) ~[mybatis-3.4.4.jar:3.4.4]
        at sun.reflect.GeneratedMethodAccessor306.invoke(Unknown Source) ~[na:na]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_151]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_151]
        at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:433) ~[mybatis-spring-1.3.1.jar:1.3.1]
        ... 19 common frames omitted







원인


 insert into TableA 로직이 수행되는 시점의 직전에
다른 모듈에서 TableA 를 select 하여 다른 테이블에 insert 하는 로직이 수행되었다.

1004lucifer
트랜잭션 관련 이슈로 인해 문제가 발생을 했으며 아래 링크의 글을 읽어보면 해당 이슈에 대해서 이해할 수 있다.
MySQL 트랜잭션 Isolation Level로 인한 장애 사전 예방 법
MySQL 5.7 Reference Manual - SET TRANSACTION Syntax
MySQL 5.7 Reference Manual - Transaction Isolation Levels


해결방안 적용시 아래의 문제가 생길 가능성 있는것 같음.
(binlog 관련 - 추후 문제 발생 시 이 글을 업데이트 예정)
[MySQL] innoDB transaction isolation level과 binlog enable 시 문제점 정리




해결방안
1004lucifer
my.cnf 파일에 아래의 옵션을 추가 후 MySQL, Java 프로그램 재기동
(4가지 옵션이 있으며 '원인' 부분에 제공된 링크를 보고 본인에 맞게 적용하면 된다.)
- READ-UNCOMMITTED
- READ-COMMITTED
- REPEATABLE-READ
- SERIALIZABLE


[mysqld]
transaction-isolation    = READ-COMMITTED




PS.
애플리케이션에서 트랜잭션이 일어나지 않게 설계를 하면 좀 더 좋겠지만 그렇지 않을 수 있다. Oracle 사용할 때는 위와같은 이슈로 고민해본적은 없었는데..
아마 Oracle 에서는 'READ-UNCOMMITTED | READ-COMMITTED' 둘중에 하나의 개념을 기본으로 사용하고 있지 않을까 싶다.



2017년 11월 11일 토요일

[Angular 2+] multipart 보낼 시 헤더에 Content-type 추가하기





작업환경: Angular 4



기존 글에 이어 수정해야 할 부분이 있어 추가로 글을 쓰게 되었다.

이전글
 - [Angular 2+] Form Submit 할 시 파일 포함하기 (multipart) - File Upload






Form Submit 할 시 문제가 되었던 부분은 아래와 같다.

Request 내용을 확인해보니 각각의 파라메터에 Content-Type이 생성되지 않고 Content-Disposition이 붙어서 Request가 발생을 했다.
그러다보니 서버사이드에서 사용하는 Spring의 객체에 데이터가 들어가지 않게 되었다.



스펙을 보니 FormData Object 에 파라메터를 추가 시 Content-Disposition 헤더가 붙는다고 기술되어 있다.
https://developer.mozilla.org/en-US/docs/Web/API/FormData/Using_FormData_Objects




서버사이드 Spring 에서 파일과 같이 객체에 데이터를 받기위해 아래와 같이 작업을 했다.

1004lucifer

multipart-form.service.ts
import {Injectable} from '@angular/core';
import {FormGroup} from '@angular/forms';
import {Headers, Http, RequestMethod, Response} from '@angular/http';
import { Observable } from 'rxjs/Rx';

@Injectable()
export class MultipartFormService {

    constructor(
        private http: Http
    ) {
    }

    /**
     * Object / File 객체를 Multipart 로 묶어서 서버에 전송한다.
     * @param {requestMethod} RequestMethod
     * @param {string} url
     * @param {Object} jsonObject
     * @param {Array<{name: string; file: File}>} files
     * @returns {Observable<Response>}
     */
    sendMultipartJsonObject(requestMethod: RequestMethod, url: string, jsonObject: Object, files?: Array<{name: string, file: File}>): Observable<Response> {

        const formData = new FormData();

        let blob;
        for (const key in jsonObject) {
            if (jsonObject.hasOwnProperty(key)) {
                blob = new Blob([jsonObject[key]], {type: 'application/json; charset=UTF-8'});
                formData.append(key, blob);
            }
        }

        if (files) {
            files
                .filter((file) => file.name != null && file.file != null)  // 정상적이지 않은 객체 Filter
                .forEach((file) => {
                    formData.append(file.name, file.file);
                });
        }

        const headers = new Headers({'enctype': 'multipart/form-data'});
        return requestMethod === RequestMethod.Post ? this.http.post(url, formData, { headers }) :
            requestMethod === RequestMethod.Put ? this.http.put(url, formData, { headers }) : null;
    }

    extractFile(event) {
        const files = event.target.files || event.srcElement.files;
        return files.length === 0 ? null : files[0];
    }
    extractFileName(event) {
        const file = this.extractFile(event);
        return file ? file.name : '';
    }
}

1004lucifer

devices.component.ts
import {Component, Input, OnInit} from '@angular/core';
import {RequestMethod} from '@angular/http';
import {MultipartFormService} from '../../shared/multipart-form/multipart-form.service';

@Component({
    selector: 'jhi-devices',
    templateUrl: './devices.component.html',
    styles: []
})
export class DevicesComponent implements OnInit {

    private readonly apiUrl = '/api/urlname';

    isNew: boolean;

    deviceInfo: Device;

    file1: File;
    file2: File;

    constructor(
        private multipartFormService: MultipartFormService
    ) {
    }

    onSubmit() {
        this.multipartFormService.sendMultipartJsonObject(
            this.isNew ? RequestMethod.Post : RequestMethod.Put,
            this.apiUrl,
            {'device': JSON.stringify(this.deviceInfo)},
            [{'name': 'file1', 'file': this.file1}, {'name': 'file2', 'file': this.file2}]
        ).subscribe(
            (response) => console.log(response.json()),
            (response) => console.log(response.json())
        );
    }

}



DeviceResource.java
/**
 * REST controller for managing Device.
 */
@RestController
@RequestMapping("/api")
public class DeviceResource {

    /**
     * POST  /devices : Create a new device.
     *
     * @param device the device to create
     * @return the ResponseEntity with status 201 (Created) and with body the new device, or with status 400 (Bad Request) if the device has already an ID
     * @throws URISyntaxException if the Location URI syntax is incorrect
     */
    @PostMapping("/devices")
    @Timed
    public ResponseEntity<Device> createDevice(
  @RequestPart Device device, 
  @RequestParam (value = "file1", required = false) MultipartFile file1, 
  @RequestParam (value = "file2", required = false) MultipartFile file2
 ) throws URISyntaxException {
  
        log.debug("REST request to save Device : {}", device);
        if (device.getId() != null) {
            return ResponseEntity.badRequest().headers(HeaderUtil.createFailureAlert(ENTITY_NAME, "idexists", "A new device cannot already have an ID")).body(null);
        }
        if (file1 != null) {
   // File 저장 로직
        }

        if (file2 != null) {
   // File 저장 로직
        }
  
  // 이후 로직 ..
  
    }
}



PS.
정석대로 한다면 Header에 multipart-mixed로 지정을 하고 일반 파라메터에는 filename 같은게 붙으면 안되지만..
위의 방법으로는 blob를 사용함으로써 쓸데없는 헤더가 붙어 제대로된 방법은 아니나, 작동하는데 크게 문제가 없으며, 이해하기 쉽고 소스가 많이 줄어 그냥 위와같이 하게 되었다.
1004lucifer
아래의 방법을 한번 볼 필요가 있다. (소스가 깔끔하지는 않다..ㅠ)
https://stackoverflow.com/questions/28133289/angularjs-how-to-send-multipart-mixed




참고
- https://ko.wikipedia.org/wiki/MIME
- https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest#Submitting_forms_and_uploading_files
- http://restlet.com/company/blog/2016/08/29/whats-new-in-the-http-module-of-angular-2/   (나와 같은 방법으로 작업이 되어있다. 깔끔한 설명!!!)



[Spring Boot] 기동 시 발생하는 SpringBootServletInitializer 에러





IDE(IntelliJ)에서 Spring Boot - MainApplication.java 를 기동하려 했는데
아래와 같은 에러가 발생을 하면서 기동되지 않았다.




  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.5.2.RELEASE)

2017-11-11 11:10:16.266  INFO 54148 --- [           main] k.c._.test.MainApplication         : Starting MainApplication on 1004lucifer-han with PID 54148 (C:\Users\1004lucifer\IdeaProjects\test\test-core\target\classes started by 1004lucifer in C:\Users\1004lucifer\IdeaProjects\test)
2017-11-11 11:10:16.275  INFO 54148 --- [           main] k.c._.test.MainApplication         : No active profile set, falling back to default profiles: default
2017-11-11 11:10:17.753  WARN 54148 --- [           main] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [kr.co._1004lucifer.test.MainApplication]; nested exception is java.lang.IllegalStateException: Failed to introspect annotated methods on class org.springframework.boot.web.support.SpringBootServletInitializer
2017-11-11 11:10:17.777 ERROR 54148 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Destroy method on bean with name 'org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory' threw an exception

java.lang.IllegalStateException: ApplicationEventMulticaster not initialized - call 'refresh' before multicasting events via the context: org.springframework.context.annotation.AnnotationConfigApplicationContext@6fec725d: startup date [Sat Nov 11 11:10:16 KST 2017]; root of context hierarchy
at org.springframework.context.support.AbstractApplicationContext.getApplicationEventMulticaster(AbstractApplicationContext.java:404) [spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.context.support.ApplicationListenerDetector.postProcessBeforeDestruction(ApplicationListenerDetector.java:97) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:253) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroyBean(DefaultSingletonBeanRegistry.java:578) [spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingleton(DefaultSingletonBeanRegistry.java:554) [spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingleton(DefaultListableBeanFactory.java:961) [spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingletons(DefaultSingletonBeanRegistry.java:523) [spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingletons(DefaultListableBeanFactory.java:968) [spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.destroyBeans(AbstractApplicationContext.java:1033) [spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:555) [spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:370) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:314) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1162) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1151) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
at kr.co._1004lucifer.test.MainApplication.main(MainApplication.java:74) [classes/:na]

2017-11-11 11:10:17.846 ERROR 54148 --- [           main] o.s.boot.SpringApplication               : Application startup failed

org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [kr.co._1004lucifer.test.MainApplication]; nested exception is java.lang.IllegalStateException: Failed to introspect annotated methods on class org.springframework.boot.web.support.SpringBootServletInitializer
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:180) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:308) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:228) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:270) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:93) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:686) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:524) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:370) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:314) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1162) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1151) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
at kr.co._1004lucifer.test.MainApplication.main(MainApplication.java:74) [classes/:na]
Caused by: java.lang.IllegalStateException: Failed to introspect annotated methods on class org.springframework.boot.web.support.SpringBootServletInitializer
at org.springframework.core.type.StandardAnnotationMetadata.getAnnotatedMethods(StandardAnnotationMetadata.java:163) ~[spring-core-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.context.annotation.ConfigurationClassParser.retrieveBeanMethodMetadata(ConfigurationClassParser.java:374) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:308) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:244) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:197) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:166) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
... 12 common frames omitted
Caused by: java.lang.NoClassDefFoundError: javax/servlet/ServletContext
at java.lang.Class.getDeclaredMethods0(Native Method) ~[na:1.7.0_80]
at java.lang.Class.privateGetDeclaredMethods(Class.java:2625) ~[na:1.7.0_80]
at java.lang.Class.getDeclaredMethods(Class.java:1868) ~[na:1.7.0_80]
at org.springframework.core.type.StandardAnnotationMetadata.getAnnotatedMethods(StandardAnnotationMetadata.java:152) ~[spring-core-4.3.7.RELEASE.jar:4.3.7.RELEASE]
... 17 common frames omitted
Caused by: java.lang.ClassNotFoundException: javax.servlet.ServletContext
at java.net.URLClassLoader$1.run(URLClassLoader.java:366) ~[na:1.7.0_80]
at java.net.URLClassLoader$1.run(URLClassLoader.java:355) ~[na:1.7.0_80]
at java.security.AccessController.doPrivileged(Native Method) ~[na:1.7.0_80]
at java.net.URLClassLoader.findClass(URLClassLoader.java:354) ~[na:1.7.0_80]
at java.lang.ClassLoader.loadClass(ClassLoader.java:425) ~[na:1.7.0_80]
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) ~[na:1.7.0_80]
at java.lang.ClassLoader.loadClass(ClassLoader.java:358) ~[na:1.7.0_80]
... 21 common frames omitted


Process finished with exit code 1






servlet 관련 오류가 보이길래 혹시 이전에 War 파일로 패키징 하기위한 부분에 문제가 있나 싶어 확인해보니 tomcat 관련 부분이 추가되어 있었다.

아래의 tomcat 을 제거하니 MainApplication.java 가 정상적으로 기동이 되었다.


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
    <groupId>kr.co._1004lucifer.realestate_core</groupId>
 <artifactId>test-core</artifactId>
 <packaging>war</packaging>
 <name>test-core</name>
    <version>0.0.1_SNAPSHOT</version>

    <parent>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot</artifactId>
        <version>1.3.0</version>
    </parent>

 <properties>
  <java.version>1.7</java.version>
  <tomcat.version>7.0.78</tomcat.version>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <start-class>kr.co._1004lucifer.test.MainApplication</start-class>
        <failOnMissingWebXml>false</failOnMissingWebXml>
    </properties>

 <dependencies>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
   <version>1.5.2.RELEASE</version>
  </dependency>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-tomcat</artifactId>
   <scope>provided</scope>
  </dependency>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
   <scope>test</scope>
  </dependency>

  <!-- Spring Boot Mail -->
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-mail</artifactId>
   <version>1.4.3.RELEASE</version>
  </dependency>

  <!-- MyBatis Spring Boot -->
  <dependency>
   <groupId>org.mybatis.spring.boot</groupId>
   <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.0</version>
  </dependency>
  <dependency>
   <groupId>org.mybatis.spring.boot</groupId>
   <artifactId>mybatis-spring-boot-starter-test</artifactId>
   <version>1.3.0</version>
  </dependency>

  <!-- MySQL DataBase -->
  <dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <version>5.1.42</version>
  </dependency>

  <!-- Lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.0</version>
        </dependency>

  <!-- HTML Parser -->
  <dependency>
   <groupId>org.jsoup</groupId>
   <artifactId>jsoup</artifactId>
   <version>1.10.2</version>
  </dependency>

 </dependencies>

 <build>
  <plugins>
   <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <version>1.5.3.RELEASE</version>
   </plugin>
  </plugins>
 </build>
</project>



2017년 11월 9일 목요일

[IntelliJ] SVN commit 시 발생하는 E720005 오류 증상






IntelliJ ver: 2017.2.5



증상

SVN commit 작업 시 아래와 같이 warning 이 발생했다.



 Warning: not all local changes may be shown due to an error: svn: E720005: Can't check path '~~~'

1004lucifer




해결방법

별다른 방법이 있는게 아니고 IntelliJ를 재구동하면 SVN 커밋 시 warning 이 없어지며 정상적으로 이용이 가능하다.


참고
https://stackoverflow.com/questions/25272326/jetbrains-warning-not-all-local-changes-may-be-shown-due-to-an-error-svn-e2