728x90

종종 빨간색으로 뜨는 글자들에는 Cannot resolve symbol 'java', 'String', 'Scanner' 등이 제대로 import 되지 않고서 에러가 뜰 때가 있습니다.

이런 현상의 가장 큰 원인은 Module SDK is not defined 이라는 에러로 Moduel SDK가 제대로 정의되지 않아서 생기는 에러가 일 가능성이 있습니다.

종종 IntelliJ를 업데이트를 하면서 IntelliJ의 JAVA  버전으로 설정하고 사용하는 경우에 발생할 수 있습니다.

JAVA 버전이 업데이트 되면서 기존에 사용하던 JAVA 설치 파일 경로의 링크가 변경되는 경우가 있기 때문입니다.

 

그래서 IntelliJ의 JAVA 설정을 변경해줘야 합니다.

 

Proejct Structure에서 Platform Settings  > SDKs 를 누릅니다.

 

+ 를 눌러서 Add New SDK 에서 JDK를 선택합니다.

 

새로 설치한 JAVA 버전이 있는 경로롤 찾아서 선택해 줍니다.

Apply 버전을 눌러서 적용시킨 다음에 "OK" 파란색 버튼을 눌러주세요.

 

그러면 새롭게 지정된 JAVA버전에 맞게 intelliJ가 index을 새롭게 구축하게 됩니다.

이렇게하면 java 버전에 맞게 모듈이 새롭게 구축되어 에러가 나타나진 않을 것입니다.

 

 

Module SDK is not defined / Cannot resolve symbol 'java', 'String', 'Scanner' 등이 빨간색

728x90

IntelliJ IDEA를 쓰고 있으며, 멀쩡히 잘 쓰다가 종종 잊을만하면 Cannot resolve symbol.. 에러가 날때가 있습니다.

 

예를 들면 아래와 같이 import가 제대로 안되어 있는 경우가 그런 경우입니다.

cannot resolve symbol import org.openjdk.jmh.runner.options.Options;

시도 방법 1

상단 메뉴바에서 Build > Clean Project 하고나서 Build > Rebuild Project를 해줍니다.

 

시도 방법 2

시도 방법 1로도 해결이 안되면 캐시를 비우고 재실행 해봅니다.

상단 메뉴바에서 File > Invalidate Caches / Restart…를 선택하고 IDE를 재실행합니다.

 

 

 

 
728x90

출처

https://ddolcat.tistory.com/26

http://blog.naver.com/PostView.nhn?blogId=netrance&logNo=221224761858&parentCategoryNo=&categoryNo=95&viewDate=&isShowPopularPosts=true&from=search

 

 

앱을 삭제했을 때 shared preference 데이터를 삭제하는 방법
How to remove shared preference while application uninstall in android

 

앱을 삭제 후 재설치하게 되면 공유환경 설정(shared preference)에서 일부 데이터가 복원되는 증상이 요즈음 나온 최신 폰에서 발생하고 있습니다.

즉, 앱을 삭제 후 재설치하면, 삭제 전에 저장되었던 자료들이 남아있는 문제가 발견되고 있습니다.

 

원인은 바로 자동 백업 "BackupManager" 때문 -- android:allowBackup 속성 true로 자동 설정

Android API 23(또는 Android "6.0" 또는 Android "Marshmellow")이후 BackupManager는 공유 환경 설정을 포함한 앱의 모든 데이터를 클라우드에 저장합니다.

이는 안드로이드 6.0부터는 AndroidManifest.xml 파일에서 application 요소의 android:allowBackup 속성을 명시하지 않으면 자동으로 true로 설정하기 때문인데 이로 인해 사용자도 모르게 데이터가 구글 클라우드에 자동으로 백업됩니다.

 

결국 앱 삭제 후 재설치하면, 자료가 자동으로 복원되다 보니 환경설정(preferences)에 저장된 자료가 되살아 나는 것입니다.

 


해결방법

 

1. 안드로이드 폰에서 직접 해제 하는 방법이 있습니다.
   설정 > 백업 및 재설정 > 자동복원을 선택, 자동복원 해제 를 하는 방법입니다.
   그러나 이 방법은 장치에 설치된 모든 응용 프로그램의 자동 백업기능을 해제하기 때문에 권장하지 않습니다.


2. 앱 소스에서 매니페스트 파일로 이동, application 태그에서 "allowBackup" 속성을 찾아서 false로 설정하는 것입니다.

 


앱의 데이터 자동 백업을 막는 방법

 

1. AndroidManifest.xml 파일을 여세요.

 

2. application 요소에 android:allowBackup 요소를 추가하고, 값을 false로 설정하세요.

android:allowBackup="false"

 

3. application 요소에 android:fullBackupContent 요소를 추가하고, 값을 false로 설정하세요.

android:fullBackupContent="false"

 

4. (옵션) 프로젝트에 다른 플러그인이 있는 경우, allowBackup 속성이 충돌할 수 있습니다.

    이 경우 application 요소에 tools:replace 속성을 추가하고, 값은 "android:allowBackup"으로 설정합니다.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tools="http://schemas.android.com/tools"
          package="패키지명">

    <uses-feature
        android:name="android.hardware.camera"
        android:required="true"/>

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>


......


    <application
        android:name=".MyApp"

        android:allowBackup="false"
        android:fullBackupContent="false"
        tools:replace="android:allowBackup"
        
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        android:usesCleartextTraffic="true"
        tools:replace="android:icon">

......


    </application>

</manifest>

 

참고로 android:fullbackupOnly="false" 기능은 안드로이드 API 21 이후 폰에서 설정, 사용가능합니다.

 

 

<기타 참고 사이트>

https://stackoverflow.com/questions/33169618/an-android-app-remembers-its-data-after-uninstall-and-reinstall

https://developer.android.com/guide/topics/data/autobackup.html

http://androbook.tistory.com/entry/%EB%8B%A4%EC%8B%9C-%EC%82%B4%ED%8E%B4%EB%B3%B4%EB%8A%94-%EB%A7%A4%EB%8B%88%ED%8E%98%EC%8A%A4%ED%8A%B8-%EC%86%8D%EC%84%B1%EB%93%A4

 

728x90

 

Android 개발 가이드 / Android 개발 가이드라인 / Android 코딩 스타일 가이드

http://developer.gaeasoft.co.kr/development-guide/android-guide/android-coding-style-guide/

 

Follow Field Naming Conventions

가. Non-public, non-static field 는 m으로 시작

예) 
private int mPrivate;

int mPackagePrivate;

protected int mProtected;

 

 

나. Static field 는 s로 시작

예) private static MyClass sSingleton;

 

다. 나머지는 소문자로 시작.

 예) public int publicField;

 

라. Public static final fields (상수) 는 모두 대문자로 ALL_CAPS_WITH_UNDERSCORES.

예) public static final int SOME_CONSTANT = 42;

 

public class MyClass {

	public static final int SOME_CONSTANT = 42;

	public int publicField;

	private static MyClass sSingleton;

	int mPackagePrivate;

	private int mPrivate;

	protected int mProtected;

}

 

시작 중괄호는 "{" 따로 한줄을 차지하지 않는다.

class MyClass {

	int func() {

		if (something) {

			// ...

		} else if (somethingElse) {

			// ...

		} else {

			// ...

		}
	}
}

 

if (condition) body();

 

TODO 주석문 또는 FIXME 주석문을 사용 할 것.

단기처방이나, 완벽하지 않은 해결책인 경우에는 반드시 TODO or FIXME주석문을 기입할 것.

// TODO: UrlTable2

또는

// FIXME: flag

 


Activity 개발 시 주의 사항

context를 별도 멤버로 선언하고 관리하지 않도록 하자.

context가 필요하면 getContext() 를 사용하자.

 

잘못된 사례

아래 예시는 잘못된 예시입니다.

public class MyActivity extends Activity {

	private Context mContext = null;

	...

	...

	protected void onCreated(Bundle savedInstanceState){

	mContext = this;

}

 


JavaTests Style Rules

테스트 방법 명명 규칙 준수

Test Method 의 이름을 설계할 때, test case를 "_" 뒤에 붙여줄 수 있다.

예)

testMethod_specificCase1 testMethod_specificCase2

void testIsDistinguishable_protanopia() {
 ColorMatcher colorMatcher = new ColorMatcher(PROTANOPIA)
 assertFalse(colorMatcher.isDistinguishable(Color.RED, Color.BLACK))
 assertTrue(colorMatcher.isDistinguishable(Color.X, Color.Y))
}

 


로깅(Log)은 간결하게.

로깅은 성능에 지대한 영향을 준다.

로깅하기 전에 먼저, 로그 레벨을 이해하자.

 

ERROR 레벨: 항상 기록되는 레벨, 뭔가 치명적인 상황을 기록한다.

따라서 조심스럽게 사용해야 한다. 먼가 치명적인 상황을 기록한다.

예를 들어 어떤 데이터를 직접 삭제하거나, 앱을 지우거나, 폰을 싹 밀어버리거나 하기 전에는 복구가 안되는 상황을 사용자가 직면해야 할때만 기록하고, (가능하면)통계수집 서버에 통보하도록 하자.

 

WARNING 레벨: 항상 기록되는 레벨, 심각한 상황을 기록한다.

심각한 상황을 기록한다.

예를 들어 사용자가 인식할 수 있는 오류결과가 나타나고, 사용하던 데이터(다운로드 중인 데이터 등등)가 날아가버리고,

사용자가 앱 혹은 폰을 리부팅하거나, 화면을 죽이거나, 새로운 버전의 앱을 다운 받기 전에는 복구가 안되는 상황에 사용하자.

 

0 INFORMATIVE: 역시 항상 기록되는 레벨, 오류가 아닌 뭔가 대단한 상황일 경우 기록한다.

오류는 아니더라고, 뭔가 모두가 알았으면 하는 대단한 상황일 경우 기록한다.

예를 들어 오류는 아니지만, 동접자 수가 100만명이 넘어갔다거나, 악성코드로 의심되는 입력값이 감지되었다거나 등등 모두가 알면 좋을 만한 사건이 발생한 상황에 사용하자.

 

DEBUG 레벨: 디버그 모드에서만 기록되는 레벨, 디버깅 과정과 관련된 추가 정보를 기록한다.

디버깅 과정과 관련한 추가 정보를 기록할 때 사용한다.

만약 로깅 자체보다는 개발자 본인의 관심사와 관련한 정보라면 verbose level로 로깅하자.

 

배포 버전에도 로깅이 가능하며, 로깅과 관련한 소스가 컴파일 되기 때문에 성능을 고려한다면

로깅 소스는 반드시 다음과 같이 if (LOCAL_LOG) or if (LOCAL_LOGD) 구문내에 구현해야 한다.

 

혹시나, 다른 대안으로 리펙토링을 통해 logging 기능을 밖으로 빼는 방법을 생각해보기도 하는데 (re-factoring out), 이는 좋은 생각이 아니다.

왜냐하면, String 파라미터가 전달되면서 불필요한 String 생성이 발생하기 때문이다.

 

VERBOSE 레벨: 뭐든 로깅해도 되는 레벨, 개발자 본인의 관심사와 관련된 정보 등을 기록한다.

debug level 처럼 반드시 if구문내에 구현하도록 하자.

아니면 배포전에 아예 없애버리자.

 


기억할 것

1. VERBOSE 레벨 이 아닐경우 - 상위 method 오버로딩 시 상위 method에 logging하자.

하나의 모듈 내에 있는 하나의 function chain 내에서 오류는 가능한 한번만 보고(logging)가 되도록 해야 한다.

이를테면 method overloading 방식으로 methodA(param1) 가 methodA(param1, param2)를 호출하면 error는 methodA(param1, param2) 에서만 기록하도록 하자.

그래야 issue를 격리시키는 게 쉬워진다.

 

2. VERBOSE 레벨 이 아닐경우 2 - 상위 모듈에 전달된 DATA 가 문제가 될 경우, debug모드로 

연쇄적으로 작동하는 모듈간에 만약 상위 모듈에서 전달된 data에 문제가 있다고 판단될 경우 로깅을 하려면 debug 모드로 해야 한다.

굳이 information 이상 레벨의 로깅이 필요하다면, 상위 레벨 모듈에서 처리해야한다.

특히 lib 나 프레임워크개발시에 이런 규칙이 중요하다.

lib 나 framework를 가져다 쓰는 경우 마음대로 로깅을 남기고 곤란한 경우가 발생한다.

 

3. 반복되거나 동일한 작업이 예상되는 것은 일정한 조건을 걸어서 로깅해라.

이를 테면, onTouchEvent 내에 로깅할때 네트웍 단절 상태등은 충분히 예상되는 내용이다. debug verbose 이상의 로깅을 하지 말자.

 

 

4. 다른 앱에서 접근가능한 파일시스템 용량 초과 같은 이슈는 INFORMATIVE 이하 레벨로 검증 되지 않은 소스로부터 들어오는 잘못된 데이터 입력등의 이슈는 DEBUG 이하로 작성할 것.

 

5. Log.v() 는 배포버전에서도 컴파일 된다.

레벨에 따라 로깅이 안될 뿐이지. 따라서 반드시 if 구문안에서 String을 처리해야함.

 

 

6. 모든 로깅은 간결하고 누구나 쉽게 이해할 수 있어야 한다.

작성자만 알아볼 수 있게 하지 말 것. (DEBUG level 이상의 로깅이라면 말이지)

 

7. 가능한 한줄로 표현되게끔 해주세요. 너무 길지도 않게.

 

8. 작업 성공 여부 같은 것은 VERBOSE 외에선 사용하지 말 것.

 

9. 검사나 분석을 위한 임시 로깅은 반드시 DEBUG or VERBOSE level 에서만 작성할 것.

 

10. 로깅으로 개인정보 등 보안 정보가 유출되지 않도록 각별히 신경 쓸것.

 

11. System.out.println()(or printf() for native code) 는 절대 사용하지 말것.

System.out와 System.err는 /dev/null 로 연결되므로 아무 기능도 안하게 되는데 괜히 StringBuilder 만 잡아 먹게 된다.

 

12. 로그가 로그를 만들게 하지 말자.

 

 

 

728x90

http://blog.naver.com/PostView.nhn?blogId=stork838&logNo=220142660973&parentCategoryNo=&categoryNo=37&viewDate=&isShowPopularPosts=true&from=search

 

멀티파트파일을 java.io.File로 변환하기 ( converting MultipartFile to File )

스프링에서 제공하는 멀티파트파일객체를 자바의 파일객체로 변환하는 방법을 소개한다.public File conve...

blog.naver.com

 

https://cnpnote.tistory.com/entry/SPRING-%EB%A9%80%ED%8B%B0-%ED%8C%8C%ED%8A%B8-%ED%8C%8C%EC%9D%BC%EC%9D%84-%ED%8C%8C%EC%9D%BC%EB%A1%9C-%EB%B3%80%ED%99%98%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95

 

[SPRING] 멀티 파트 파일을 파일로 변환하는 방법?

멀티 파트 파일을 파일로 변환하는 방법? 다중 파트 파일 (org.springframework.web.multipart.MultipartFile)을 File (java.io.File)로 변환하는 가장 좋은 방법은 무엇입니까? 내 봄 mvc 웹 프로젝트에서 나는 M..

cnpnote.tistory.com

 

public File convert(MultipartFile file)
{    
    File convFile = new File(file.getOriginalFilename());
    convFile.createNewFile(); 
    FileOutputStream fos = new FileOutputStream(convFile); 
    fos.write(file.getBytes());
    fos.close(); 
    return convFile;
}
public File multipartToFile(MultipartFile multipart) throws IllegalStateException, IOException 
{
    File convFile = new File( multipart.getOriginalFilename());
    multipart.transferTo(convFile);
    return convFile;
}

 

스프링에서 제공하는 multipartFile을 자바의 파일 객체 File로 변환하기 / transferTo / createNewFile() / FileOutputStream

728x90

YouTube API에서  썸네일을 업로드할려고 하는데 자꾸 forbidden 에러가 뜹니다.

처음에는 인증이 잘못되어서 그런 것인줄 알았는데 순전히 퍼미션 에러 였습니다.

그래서 퍼미션 권한을 부여해주니 에러없이 업로드 가 되었습니다.

 

"맞춤 동영상 미리보기 이미지 만들기"는 해당 계정에서 이를 확인해줬거나 실시간 스트리밍 액세스 권한이 있는 경우에만 동영상 업로드를 위한 "맞춤 미리보기 이미지"를 업로드 할 수 있습니다.

 

The authenticated user doesnt have permissions to upload and set custom video thumbnails.

"인증 된 사용자에게는 맞춤 동영상 미리보기 이미지를 업로드하고 설정할 수있는 권한이 없습니다"

 

You chose 비디오아이디 to upload a thumbnail.
Video files from /Users/jaehonghan/dev/youtubeUploadFiles:
 0 = 20200402.png
Choose the number of the video file you want to upload: 0
You chose /Users/jaehonghan/dev/youtubeUploadFiles/20200402.png to upload.
Initiation Started
Initiation Completed
GoogleJsonResponseException code: 403 : The authenticated user doesnt have permissions to upload and set custom video thumbnails.
com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden
{
  "code" : 403,
  "errors" : [ {
    "domain" : "youtube.thumbnail",
    "location" : "Authorization",
    "locationType" : "header",
    "message" : "The authenticated user doesnt have permissions to upload and set custom video thumbnails.",
    "reason" : "forbidden"
  } ],
  "message" : "The authenticated user doesnt have permissions to upload and set custom video thumbnails."
}
	at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:150)
	at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:113)
	at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:40)
	at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:432)
	at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:352)
	at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:469)
	at com.tubro.youtube.thumbnails.test.ThumbnailsSetTest.main(ThumbnailsSetTest.java:124)

Process finished with exit code 0

 

아래에 접속하셔서 업로드하고자 하는 계정에 대해서 권한을 부여해 주세요 !!

https://www.youtube.com/verify

 

 

Contiune  버튼을 클릭하시면 해당 계정에 대한 퍼미션 인증에 대한 것들이 뜨게 됩니다.

아래 이미지에서 Custom thumbnails  가 Enabled가 뜨는 것을 확인할 수 있습니다.

 

 

만약에 아래와 같은 화면이 뜨지 않더라도 당황하지 마시고 퍼미션을 얻기 위해 버튼을 클릭해 주세요.

저 같은 경우에도 휴대폰이나 이메일 주소 인증을 통해서 실제 해당 계정에 대한 권한을 갖기 위한 확인 절차를 거쳤습니다.

휴대폰번호를 입력하고 나니 직접 구글에서 연락이 오더라구요. 

영어로 막 얘기를 하는데 ARS이니 그냥 듣고 계시다가 6자리 확인 숫자를 불러주니 그걸 잘 들으시고 입력해 주시면 됩니다.

(한국어가 아닌 영어이니 원,투,쓰리 로 말하니 잘 들으세요 ..ㅋㅋㅋ)

 

 

인증을 거치고 나서 퍼미션 권한을 획득 하시고 나서 다시 실행 해보세요.

Thumbnail이 제대로 올라가는 것을 확인하실 수 있을 것입니다.

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/Users/jaehonghan/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/Users/jaehonghan/.m2/repository/org/slf4j/slf4j-log4j12/1.7.30/slf4j-log4j12-1.7.30.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder]

You chose "비디오아이디" to upload a thumbnail.
Video files from /Users/jaehonghan/dev/youtubeUploadFiles:
 0 = 20200402.png
Choose the number of the video file you want to upload: 0
You chose /Users/jaehonghan/dev/youtubeUploadFiles/20200402.png to upload.
Initiation Started
Initiation Completed
Upload Completed!

================== Uploaded Thumbnail ==================

  - Url: https://i.ytimg.com/vi/비디오아이디/default.jpg

Process finished with exit code 0

 

 

728x90

lombok@Slf4j 를 이용해서 

와 같이 코드를 만들어서 사용할려고 할때

"Cannot resolve symbol log" 라는 경고가 뜨면서 실행이 안되는 경우가 있습니다

 

 

이때는 lombok plugin 을 설치해줍니다.

Preferences -> Plugins -> Browse repositories... -> search lombok -> Install "IntelliJ Lombok plugin" 을 설치해 주세요.

그리고 IntelliJ IDE를 재 실행해 주세요.

 
728x90

"System.getProperty()" 사용법

자바를 실행할 때, 실행되는 곳의 정보를 얻어오거나 운영체제의 정보가 필요할 때가 있습니다.
실행 위치에 있는 파일을 읽어드려야 하는데, 현재 위치를 알 수 있는 방법 등 시스템의 정보를 가져올때  System.getProperty() 를 사용합니다.

 

System.getProperty() 으로 괄호 안에 주어진 특정 문자를 적어넣으면 그 값이 String 으로 출력됩니다.

String dir = System.getProperty("user.home");
System.out.println(dir);


// 리눅스 인 경우 /home/유저명/
// macOS인 경우 //Users/유저명/

 

Property 주요 검색어

검색어
java.version Java 버전
java.vendor Java 공급자
java.vendor.url Java 공급자 주소
java.home Java를 설치한 디렉토리
java.class.version Java 클래스 버전
java.class.path Java 클래스 경로
java.ext.dir 확장기능의 클래스 경로
os.name 운영체제 이름
os.arch 운영체제 아키텍처
os.version 운영체제 버전 정보
file.separator 파일 구분 문자
path.separator 경로 구분 문자
line.separator 행 구분 문자
user.name 사용자 계정
user.home 사용자 홈 디렉토리
user.dir

현재 디렉토리

property 확인 메소드해보기

import java.util.Properties;
import java.util.Enumeration;

public class Test {
    public static void main(String[] args) {
        Properties props = System.getProperties();
        for(Enumeration en = props.propertyNames(); en.hasMoreElements();) {
            String key = (String)en.nextElement();
            String value = props.getProperty(key);
            System.out.println(key + "=" + value);
        }
    }

}

 

전혀 없는 키 만들기

전혀 없는 키값인데, System.getProperty("file.location.env"); 라면서 사용하는 경우가 있습니다.

이럴경우, JVM 의 VM arguments 부분을 살펴보면 다음과 같이 세팅되어 있다.

System.getProperty("file.location.env"); 

를 사용하기 위해서 JVM 의 VM arguments 부분에 설정해 주세요.

-Dfile.location.env="./fileUploads/"

 

JVM의 VM arguments 는 JVM을 구동할때, 필요한 여러가지 값을 세팅하는 것인데 -D하고 바로뒤에 키="값"을 세팅하면

프로그램내에서 System.getProperty("키"); 를 통해 값을 가져올 수 있습니다.

 

ava.runtime.name=Java(TM) 2 Runtime Environment, Standard Edition
sun.boot.library.path=C:\Program Files\Java\jdk1.5.0_18\jre\bin
java.vm.version=1.5.0_18-b02
java.vm.vendor=Sun Microsystems Inc.
java.vendor.url=http://java.sun.com/
path.separator=;
java.vm.name=Java HotSpot(TM) Client VM
file.encoding.pkg=sun.io
user.country=KR
sun.java.launcher=SUN_STANDARD
sun.os.patch.level=Service Pack 3
java.vm.specification.name=Java Virtual Machine Specification
user.dir=C:\java\client

java.runtime.version=1.5.0_18-b02
java.awt.graphicsenv=sun.awt.Win32GraphicsEnvironment
java.endorsed.dirs=C:\Program Files\Java\jdk1.5.0_18\jre\lib\endorsed
os.arch=x86
java.io.tmpdir=C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\
line.separator=

java.vm.specification.vendor=Sun Microsystems Inc.
user.variant=
os.name=Windows XP
sun.jnu.encoding=MS949
java.library.path=C:\Program Files\Java\jdk1.5.0_18\bin;

java.specification.name=Java Platform API Specification
java.class.version=49.0
sun.management.compiler=HotSpot Client Compiler
os.version=5.1
user.home=C:\Documents and Settings\Administrator
user.timezone=
java.awt.printerjob=sun.awt.windows.WPrinterJob
file.encoding=MS949
java.specification.version=1.5
user.name=Administrator
java.vm.specification.version=1.0
sun.arch.data.model=32
java.home=C:\Program Files\Java\jdk1.5.0_18\jre
java.specification.vendor=Sun Microsystems Inc.
user.language=ko
awt.toolkit=sun.awt.windows.WToolkit
java.vm.info=mixed mode, sharing
java.version=1.5.0_18
file.separator=\
java.vendor.url.bug=http://java.sun.com/cgi-bin/bugreport.cgi
sun.cpu.endian=little
sun.io.unicode.encoding=UnicodeLittle
sun.desktop=windows
sun.cpu.isalist=pentium_pro+mmx pentium_pro pentium+mmx pentium i486 i386 i86

 

출처: https://unabated.tistory.com/entry/Java에서-SystemgetProperty [랄라라]

728x90

Spring Boot Starter & Parent 로 간단히 의존성 설정하기

http://dveamer.github.io/backend/SpringBootStater.html

 

 

순수 Java 프로젝트는 필요한 라이브러리를 사용하기 위해선 라이브러리 파일들을 직접 보관하고 관리해야 했습니다. 

 

Maven, Gradle과 같은 프로젝트 관리 툴을 이용하면서 라이브러리의 정보, 버전, 의존성을 문서(pom.xml, build.gradle)에 작성만 해도 라이브러리를 사용할 수 있게 되었고 덕분에 관리와 공유할 수 있게 되었습니다.

하지만 여전히 라이브러리간의 의존성 관리와 버전 충돌은 우리들이 직접 해결하고 매번 작성해야 합니다.

 

Python은 PIP라는 패키지 매니저를 통해 패키지를 설치하면 해당 패키지와 의존성을 갖는 패키지 조합을 사전에 정의되어있는 버전에 맞게 자동으로 설치해줍니다.

PHP 7 에서는 composer를 통해서 이런 작업들을 할 수 있게 도와주고 있습니다.

nodejs 에서는 npm 에서 이런 작업들을 도와주고 있습니다.

 

그리고 Spring boot 에서도 이런 라이브러리 간의 의존성관리 및 버전 충돌에 대한 이슈를 굉장히 쉽고 빠르고 정확하게 의존성 설정을 할 수 있도록 도와주는 라이브러리가 있습니다.

 

그것이 바로 spring-boot-stater와 spring-boot-stater-parent입니다.

Spring 진영에서는 이러한 문제를 해결해주는 spring-boot-starter와 spring-boot-stater-parent를 제공했습니다. 

Spring Boot를 사용하면서 자주 사용하게 되는 라이브러리간의 의존성, 버전 조합을 각각 테스트한 뒤 공개했다고 보시면 됩니다. 

Spring 진영의 신뢰성 높은 검증을 거친 이 의존성 조합은 비록 세상 모든 라이브러리의 조합을 커버하지는 못하지만 자주 사용되는 라이브러리들에 대해서만큼은 스트레스를 받지 않고 설정할 수 있게 해줍니다.


Spring Boot Starter

프로젝트에 설정해야 할 다수의 의존성들을 사전에 미리 정의해서 의존성 조합 제공

Spring Boot에서는 spring-boot-starter라는 사전에 미리 정의한 편리한 의존성 조합을 제공합니다.

프로젝트에 설정해야하는 다수의 의존성들을 starter가 이미 포함하고 있기 때문에 우리는 starter에 대한 의존성 추가만으로도 프로젝트를 시작하거나 새로운 기능을 추가할 수 있습니다.

 

예를들어, 기존에 aspectJ를 이용한 AOP를 이용하고 싶으면

org.springframework:spring-aop 의존성과 org.aspectj:aspectjweaver 의존성을 추가해서 사용했었지만

Spring Boot에선는 spring-boot-starter-aop 의존성만 추가하면 aspectJ를 사용하기 위한 모든 의존성 조합이 추가 됩니다.

의존성 조합의 간단한 예가 AOP였던 거고 좀 더 복잡한 의존성 조합을 보고 싶으시다면 다른 starter를 확인해 보시기 바랍니다. 

 

 

또다른 예시로 spring-boot-starter-jpa를 의존성 추가했을 때 아래와 같은 일을 해줍니다.

  • spring-aop, spring-jdbc 등의 의존성을 걸어준다.

  • classpath를 뒤져서 어떤 Database를 사용하는지 파악하고, 자동으로 entityManager를 구성해 준다.

  • 해당 모듈들 설정에 필요한 properties 설정을 제공한다. (Configuration Processor를 사용하면 효과 UP)

spring-boot-starter-data-jpa v2.1.7.RELEASE은 7개의 의존성 조합을 포함하고 있고 잘 살펴보시면 그 7개의 의존성 중에 또 다른 spring-boot-starter가 존재해서 실제는 7개보다 더 많은 의존성이 설정되어 있습니다.

또한 중복되어 문제가 되는 의존성에서 대해서는 exclusion 설정도 되어 있습니다.

 

즉, spring-boot-starter-jpa 모듈을 추가함으로써 아래의 7가지 의존성 조합에 대한 부분을 알아서 정리해주고 관리해줍니다.

<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-aop</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jdbc</artifactId>
		</dependency>
		<dependency>
			<groupId>javax.transaction</groupId>
			<artifactId>javax.transaction-api</artifactId>
		</dependency>
		<dependency>
			<groupId>javax.xml.bind</groupId>
			<artifactId>jaxb-api</artifactId>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
			<exclusions>
				<exclusion>
					<groupId>org.jboss.spec.javax.transaction</groupId>
					<artifactId>jboss-transaction-api_1.2_spec</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-jpa</artifactId>
			<exclusions>
				<exclusion>
					<groupId>org.aspectj</groupId>
					<artifactId>aspectjrt</artifactId>
				</exclusion>
				<exclusion>
					<groupId>org.slf4j</groupId>
					<artifactId>jcl-over-slf4j</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aspects</artifactId>
		</dependency>
</dependencies>

 

spring-boot-starter-web 에 설정된 pom.xml 

<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starters</artifactId>
    <version>2.2.1.RELEASE</version>
  </parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
  <version>2.2.1.RELEASE</version>
  <name>Spring Boot Web Starter</name>
  <description>Starter for building web, including RESTful, applications using Spring
		MVC. Uses Tomcat as the default embedded container</description>
  <url>https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-starters/spring-boot-starter-web</url>
  <organization>
    <name>Pivotal Software, Inc.</name>
    <url>https://spring.io</url>
  </organization>
  <licenses>
    <license>
      <name>Apache License, Version 2.0</name>
      <url>https://www.apache.org/licenses/LICENSE-2.0</url>
    </license>
  </licenses>
  <developers>
    <developer>
      <name>Pivotal</name>
      <email>info@pivotal.io</email>
      <organization>Pivotal Software, Inc.</organization>
      <organizationUrl>https://www.spring.io</organizationUrl>
    </developer>
  </developers>
  <scm>
    <connection>scm:git:git://github.com/spring-projects/spring-boot.git</connection>
    <developerConnection>scm:git:ssh://git@github.com/spring-projects/spring-boot.git</developerConnection>
    <url>https://github.com/spring-projects/spring-boot</url>
  </scm>
  <issueManagement>
    <system>Github</system>
    <url>https://github.com/spring-projects/spring-boot/issues</url>
  </issueManagement>
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
      <version>2.2.1.RELEASE</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-json</artifactId>
      <version>2.2.1.RELEASE</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-tomcat</artifactId>
      <version>2.2.1.RELEASE</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-validation</artifactId>
      <version>2.2.1.RELEASE</version>
      <scope>compile</scope>
      <exclusions>
        <exclusion>
          <artifactId>tomcat-embed-el</artifactId>
          <groupId>org.apache.tomcat.embed</groupId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>5.2.1.RELEASE</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.2.1.RELEASE</version>
      <scope>compile</scope>
    </dependency>
  </dependencies>
</project>

1. Spring Boot Starter는 우리가 찾아서 설정해야 하는 것들을 미리 작성해야 보다 쉽고 빠르고 정확하게 의존성 설정을 할 수 있게 해줍니다.

2. 프로젝트를 진행하면서, 공통적으로 사용하는 spring  설정을 모듈로 묶어놓고 사용할 수 있게 해줍니다.

3. 필요한 경우, 상위 프로젝트에서 얼마든지 설정을 덮어 쓸 수 있게 해줍니다.

 

 

spring-boot-starter 작성하기

https://supawer0728.github.io/2018/03/15/create-spring-boot-starter/


Spring Boot Starter Parent 

해당 의존성 조합간의 충돌문제가 없는 검증된 버전정보 조합을 제공

 

프로젝트 시작 시기에 다양한 라이브러리들을 사용하게되면 라이브러리 버전간의 충돌문제가 발생할 수 있습니다.

Sprign Boot의 starter가 의존성 조합을 제공해준다면 starter-parent는 해당 의존성 조합간의 충돌 문제가 없는 검증 된 버전정보 조합을 제공합니다.

spring-boot-starter-parent 2.1.7.RELEASE에서 제공하는 버전정보 조합은 Maven repository - spring-boot-stater-parent 혹은 GitHub - spring-boot-stater-parent 에서 확인 가능합니다.

우리는 아래와 같이 spring-boot-starter-parent 버전만 설정해도 수많은 라이브러리들의 버전충돌 문제를 피할 수 있습니다.

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.7.RELEASE</version>
</parent>

<dependencies>
    ...(생략)

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
</dependencies>


특정 의존성이 버전을 변경하고자 한다면 아래와 같이 properties를 이용해서 해당 의존성 버전을 override하면 됩니다.

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.7.RELEASE</version>
</parent>

<properties>
    <aspectj.version>1.9.4</aspectj.version>
</properties>

<dependencies>
    ...(생략)

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
</dependencies>

 

1. spring-boot-starter-parent 라이브러리를 사용해서 추가하는 라이브러리 모듈에 대한 버전을 가이드합니다.

2. <version> 태그를 추가하지 않아도 parent 에서 자동으로 처리해줍니다.

3. <version>에 대한 내용을 변경하고자 할 경우에는 <properties> 태그를 이용해서 변경, override 해줍니다.

 

728x90

 

나는 Java/ Maven Project 를 intelliJ IDEA에서 하고 있습니다.

그런데 내가 test 를 실행할려고 할때, 아래 그림과 같이 "Noting Here" 라는 메세지가 나오면서 실행이 안되네요.

그래서 한참을 찾다가 아래와 같은 해결책을 발견하여 공유합니다.

(I have a Java / maven project in IntelliJ IDEA, but when I try to run a test I got the message "Nothing Here")

 

1. 단계

- Preferences.. 에서 Plugins 탭에서 Gradle을 찾아보세요.

- Gradle이 설치되어 있는지 살펴보고 설치되어 Enable 되어 있다면 Disable 해주세요.

Apply 버튼을 클릭하시고 IntelliJ IDEA 를 Restart 합니다.

재 실행해서 보시면 아래와 같이 뜬다면 1단계는 성공 입니다~~!!!

 

2. 단계 : disabled_plugins.txt 를 찾아 아래 내용을 삭제합니다.

org.jetbrains.idea.gradle.ext
org.jetbrains.plugins.gradle
org.jetbrains.plugins.gradle.maven

 

전 여러개의 버전이 존재하는데 현재 2019.3 버전을 사용하고 있네요.

./Library/Preferences/IntelliJIdea2018.1/disabled_plugins.txt
./Library/Preferences/IntelliJIdea2019.3/disabled_plugins.txt
./Library/Preferences/IntelliJIdea2017.2/disabled_plugins.txt
./Library/Preferences/IntelliJIdea2019.2/disabled_plugins.txt
./Library/Preferences/IntelliJIdea2017.3/disabled_plugins.txt
./Library/Preferences/IntelliJIdea2018.3/disabled_plugins.txt
./Library/Preferences/IntelliJIdea2016.2/disabled_plugins.txt
./Library/Preferences/IntelliJIdea2018.2/disabled_plugins.txt
./Library/Preferences/IntelliJIdea2016.3/disabled_plugins.txt
./Library/Preferences/IntelliJIdea2017.1/disabled_plugins.txt
./Library/Preferences/IntelliJIdea2019.1/disabled_plugins.txt

 

# vi  ./Library/Preferences/IntelliJIdea2019.3/disabled_plugins.txt

CFML Support
CloudFoundry
DevKit
GlassFish
IdeaVIM
JBoss
JSR45Plugin
Jetty
Resin
WebSphere
Weblogic
com.intellij.dmserver
com.intellij.drools
com.intellij.gradle
com.intellij.gwt
com.intellij.javaee.view
com.intellij.jboss.arquillian
com.intellij.jboss.core
com.intellij.seam
com.intellij.seam.pageflow
com.intellij.seam.pages
com.intellij.struts2
com.intellij.tapestry
com.intellij.uiDesigner
cucumber-groovy
org.intellij.grails
org.jetbrains.android
org.jetbrains.idea.gradle.ext  <<--- 찾았다 요놈!!!

 

그래도 해결 안된다면!!

마지막으로 위의 1,2단계로 해도 해결이 되지 않는다면 idea.log파일을 열어두고 해당 이슈에 대해 반복발생시켜서 살펴봐야 합니다.

(Help | Show Log In Explorer)

 

If it doesn't help, attach your idea.log file after reproducing the issue (Help | Show Log in Explorer).

 


참고 URL 

https://youtrack.jetbrains.com/issue/IDEA-228180?_ga=2.175130594.1707466865.1580292427-909525344.1568791489

https://stackoverflow.com/questions/59784808/cant-run-test-on-intellij-idea

+ Recent posts