Clojure > JAR 파일 바인딩 시키기 2.

http://ezcocoa.com/?p=1859

이전에 소개했던 방법은 사실 다른 문제로 이어진다.

문제는 :resource-paths 속성을 이용하여 처리를 하였지만 실제 excitable 파일을 만들때 leiningen 이 :resource-paths로 설정 된 jar를 포함시키지 않는 다는 것이다.

혼자서 몇 시간 동안 끙끙 대다가 구글 클로져 그룹에 글을 남김으로써 문제를 해결 할 수 있었다.

link

방법은 간단하다.

Maven으로 Local Repository를 만들어 처리할 수 있었다.

1. Add simmetrics to your local maven repo;
$ mvn install:install-file -Dfile=simmetrics_jar_v1_6_2_d07_02_07.jar -DgroupId=simmetrics -DartifactId=simmetrics -Dversion=1.6.2 -Dpackaging=jar -DgeneratePom=true

2. Refer to it in :dependencies of your project.clj file;
[simmetrics/simmetrics “1.6.2”]

3. Done :)
lein uberjar

Clojure > jar파일 바인딩 시키기.

귀국 한지 3일 째…

캐나다의 내 생활은 정말 별거 없었다. 공부 공부 공부 정말 모든 것 들을 놓았었다.

이제 다시 돌아왔으니 일도 구하고 프로그래밍도 더 열심히 그리고 Clojure 이 녀석 참 매력적이다.

캐나다에서 만들었던 (아주 작은 만한)영어 학습 프로그램을 업그레이드 할려고 마음을 먹었다.

Matching Function이라고 두개 문자열을 받아 비교하는 기능이다.

물론 ㅡ.ㅡ 시간이 없으니 이전에 구현해 놓은 쓰래기 매칭 알고리즘은 버리고 오픈 소스를 이용하기로 하였다.

이 문제를 해결하는 동안 의외로 짜증나는 문제들이 발생하였다.

Leiningen 2에서는 :extra-classpath-dirs가 동작하지 않는다는 것!

이 문제의 대안을 찾기위해 작지 않은 큰시간을 소비. 그래서 찾은 방법이

Deploying Libraries

간단하게 읽어보면 문제 해결방법은 간단하였다.

Public Or Private 공간에 라이브러리를 올려놓아 Leiningen2을 이용하여 Project.clj에 첨부하여 자동적으로 포함시키는 방법.

솔직히 나는 좀 더 시운 방법을 찾고 싶었다. 왜냐 저건 완전 Amazon S3팔아 먹는내용이잖아!!
(물론 어느정도 용량/트래픽/Etc 는 무료다. 난 내 카드정보 넣는게 싫다!)

물론 개인 서버를 운용하는 방법도 있다. (난 영어학습 프로그램을 만드는거지 서버설치까지 하고 싶지 않아!!)

고로 좀더 찾아보기로…

FAQ

오잉 아주 간단한 방법이 있엇네? 라고 씨익 웃어봤지만 이건 — 난 안되던데?

If you are just doing exploratory coding you can deploy to file:///$HOME/.m2/repository and the jars will be available locally.

구글러 여러분들의 대화 link 나와 같은 문제를 해결하기 위해.

결론!!

충격먹을 필요 없다. 정말 간단한 방법이 이렇게 있었으니……. 삽질하고 있었던 내자신이…

[sourcecode language=”clojure”]
:resource-paths [“src/main/resource”] ; Non-code files included in classpath/jar.
[/sourcecode]

ref page

Clojure > class-path 출력하기

출처 : http://pupeno.com/2008/11/26/printing-the-class-path-in-clojure/

(doseq [url (seq (.getURLs (java.lang.ClassLoader/getSystemClassLoader)))]
  (println (.getFile url)))
[/sourcecode]

[sourcecode language="clojure"]
(use 'clojure.pprint)
(import 'java.lang.Thread)
(-> (Thread/currentThread) (.getContextClassLoader) (.getURLs) (seq) (pprint))

Clojure – 문서찾기

문서 찾기

doc

REPL 상태에서 쉽게 문서를 찾을 수 있다. 가장 많이 쓰이는 함수로 doc 함수를 아래와 같이 이용하면 된다.

(doc name)

find-doc 정확한 이름을 알지 못할 때 사용할 수 있는 검색 기능으로 find-doc을 사용할 수 있다.

첫번째 인자로 들어간 값으로 Regular expression이나 문자열에 포함되어 있다면 매치 된 결과를 보여준다.

(find-doc s)

 

Clojure – 새로 시작하는 마음으로…

클로저 라이브러리에 대해서 알아보자.

클로저 코드는 Library처럼 패키지 되어 있다.

각각의 클로저 라이브러리는 네임스페이스로 되어있으며, Java 패키지와 유사한 구조로 되어있다.

만약 클로저에서 라이브러리를 호출하기 위해서 아래와 같이 사용할 수 있다.

(require quoted-namespace-symbol)

clojure.contrib.str-utils와 같은 패키지를 사용할 때

이는 clojure/contrib/str-utils.clj CLASSPATH에 위치하며 아래와 같이 사용할 수 있다.

(require 'clojure.contrib.str-utils)

Single quote(‘)는 꼭 필요하다.

Single quote는 Reader Macro의 의미를 가지며, 텍스트를 Clojure data structures로 변환하는 역할을 한다.

기본 폼에서 추가적으로 또한 클로저 리더는 리더 매크로를 구성한다.

리더 매크로는 앞 문자 케릭터로 부터 트리거를 발생시킨다?

대부분의 유사한 리더 매크로는 주석이다.

매크로 Character는 주석으로 작동되며 또한 세미콜론을 (;)의미한다.

또한 특수 리더로서 현 라인의 끝까지 모든 명령을 무시한다.

Require을 사용하지말고, Use!를 사용하자.

만약 Require을 사용한다면 네이스페이즈를 지정해주어야 한다.

refer

*refer*를 사용하면 지정된 네이스페이스 안에 있는 모든 아이템을 다 가져온다.

require 또는 use와 함께 강제적으로 모든 라이브러리를 다시 불러들이고 싶을때는

:reload-all 플래그를 사용할 수 있다.

만약 만드는 과정에서 라이브러리가 변경되거나 재시작 없이 정확한 값을 보기를 원한다면

:reload-all 플래그로 유용하게 사용할 수 있다.

 

 

 

Clojure – (read-line) doesn’t wait for input

“lein run”을 이용하여 (read-line) 함수를 사용하는 중에 문제가 발생하였다.

(read-line) 함수는 (. (new java.util.Scanner (. System in)) nextLine)]와 동일하다.

문제의 원인은 leiningen은 새로운 프로세스를 생성하여 사용하므로 사용자 콘솔에 접근을 할 수 없다는 문제이다.

ref : http://stackoverflow.com/questions/7707558/clojure-read-line-doesnt-wait-for-input

Try “lein trampoline run”. See

 Q: I don't have access to stdin inside my project.
 A: There's a problem in the library that 
Leiningen uses to spawn new processes that blocks access to console input. 
This means that functions like read-line will not work as expected in most contexts, 
though the repl task necessarily includes a workaround. 
You can also use the trampoline task to launch 
your project's JVM after Leiningen's has exited rather than launching it as a subprocess.

Clojure – Query (Insert & Delete & Query & update)

테이블명은 ‘users’ 이며 두가지의 컬럼(fname, age)을 가지고 있습니다.

1. 데이터 추가하기

[sourcecode language=”clojure”]
(insert-values
:users
["fname", "age"]
["hojun", "27"])
[/sourcecode]

2. 데이터 수정하기

[sourcecode language=”clojure”]
(update-values
:users
["fname=?"
"hojun"]
{:age "28"})
[/sourcecode]

3. 데이터 검색하기

[sourcecode language=”clojure”]
(with-query-results
results
["select fname from users"]
(doall results))

[/sourcecode]

4. 데이터 삭제하기

[sourcecode language=”clojure”]
(delete-rows
:users
["fname=?ezcocoa"])

[/sourcecode]

Clojure – Using mysql

clojure + mysql 사용하기편입니다.

1. 의존성 라이브러리 다운받기

project.clj 파일 소스안에 jdbc 라이브러리 관련하여 추가해주세요.
[sourcecode language=”clojure”]
(defproject clojql "1.0.0-SNAPSHOT"
:description "FIXME: write description"
:dependencies [[org.clojure/clojure "1.2.1"]
[org.clojure/clojure-contrib "1.2.0"] ;; for clojure.contrib.sql
[org.clojure/java.jdbc "0.0.6"] ;; jdbc
[mysql/mysql-connector-java "5.1.6"]]) ;; mysql driver
[/sourcecode]

2. 의존성 라이브러리 다운받기

아래의 명령을 통해 의존성 라이브러를 다운받습니다.
[code]
# lein deps
[/code]

3. 커넥션을 위한 디비 설정 하기

[code]
user => (use ‘clojure.contrib.sql)
nil
user=> (def db {:classname "com.mysql.jdbc.Driver"
:subprotocol "mysql"
:subname "//localhost:3306/test"
:user "root"})
[/code]

실제 커넥션 맺기

[code]
user=> (with-connection db (with-query-results rs ["select * from mytable"] (count rs)))
[/code]

저는 테이블 정보가 없기때문에 카운터가 0으로 출력되는 것을 확인 할 수 있습니다.
Result : 0

Clojure – Build a Project

ref : http://stackoverflow.com/questions/6874338/standalone-clojure-app

To build a project that, when run, prints “Hello World!”, you’d do as follows (revision of your process above):

Setup


lein new my-project
cd my-project
lein deps

You should now have a basic structure in place and the Clojure jar in your lib folder.

Write a Function

Now edit src/my_project/core.clj with your editor of choice, adding the following below the (ns …) form:

[sourcecode language=”clojure”]
(defn -main []
(println "Hello World!"))
[/sourcecode]
This function is inside your my-project.core namespace. To ensure this gets run as your main, let’s add a gen-class parameter to your namespace definition at the top, so that it now looks like this at the top of core.clj:

[sourcecode language=”clojure”]
(ns my-project.core
(:gen-class :main true))
So all together, your core.clj file looks like this:

(ns my-project.core
(:gen-class :main true))

(defn -main []
(println "Hello World!"))
[/sourcecode]

Configure it as the Main Function

Once you’ve got src/my_project/core.clj edited as above, you need to tell Leiningen (the build tool) where the “main” function for your project lives. Here’s an example defproject form that does this:
[sourcecode language=”clojure”]
(defproject my-project "1.0.0-SNAPSHOT"
:description "My Project"
:dependencies [[org.clojure/clojure "1.2.1"]]
:main my-project.core)
[/sourcecode]
Now the -main function inside my-project.core becomes the entry-point for your program.

Run It

You can now have two options for running this project:

Use lein run at the command-line while at the root of your my-project project
Create a standalone jar file by running lein uberjar. You can then run the resultant jar file by running
[code]
java -jar my-project-1.0.0-SNAPSHOT-standalone.jar[/code]

Clojure – Dependencies

Leiningen은 의존적으로 관리되는 패키지들의 집합 관리 유틸입니다. 정말 강력하죠.

지금 제가 설명드릴 내용은 Leiningen을 이용한 Clojure 프로젝트에서의 project.clj에 대한 설명입니다.

구조를 먼저 보시죠
[sourcecode language=”clojure”]
(defproject my-sandbox "1.0.0-SNAPSHOT"
:description "FIXME: write"
:dependencies [[org.clojure/clojure "1.2.0"]
[org.clojure/clojure-contrib "1.2.0"]])
[/sourcecode]

dependencies부분에 보시면 아래와 같은 형식으로 구성되어있다는 것을 확인하실 수 있습니다.
[code]
GROUP / ARTIFACT-ID VERSION
[/code]

위와 같은 형식으로 lib를 추가하신 후에 아래와 같은 입력을 해줍니다.
[code]lein deps[/code]

에러 없이 잘 수행다면 프로젝트 경로의 lib폴더 안에 .jar파일이 생성된 것을 확인할 수 있습니다.

사실 저 의존적인 파일들은 ~/.m2/repository폴더에 생성되면 다운로드가 완료되면 project/lib폴더에 복사됩니다.

그러니 만약 에러를 발생되었다면 확인할 수 있겟죠.