scala 2.9부터 List 객체의 remove 메소드가 사라졌다. Immutable 객체에 remove()가 어색했던 것 같다. 

http://www.scala-lang.org/files/archive/api/2.9.0/#scala.collection.immutable.List



2.8 버전에는 deprecated된 http://www.scala-lang.org/api/2.8.2/의 List의 remove 메소드를 확인할 수 있다.

defremove (p: (A) ⇒ Boolean) List[A]

    deprecated: 
  1. use filterNot' instead



스칼라 2.11로 테스트 해보면 다음과 같다. 


scala> thrill.remove(s=>s.length ==4)

<console>:13: error: value remove is not a member of List[String]

       thrill.remove(s=>s.length ==4)

              ^


scala> thrill.filterNot(s=>s.length==4)

res13: List[String] = List(aa, bb)


scala> thrill.filterNot(s=>s.length==2)

res14: List[String] = List()




참고로 ListBuffer에는 remove()가 존재한다. Buffer는 문맥에 맞게 제공하고 있다. 


http://www.scala-lang.org/api/current/#scala.collection.mutable.ListBuffer

  1. defremove(n: Int)A

    Removes the element on a given index position.

  2. defremove(n: Intcount: Int)Unit

    Permalink

    Removes a given number of elements on a given index position.


  1. def--=(xs: TraversableOnce[A])ListBuffer.this.type

    Removes all elements produced by an iterator from this shrinkable collection.

  2. def-=(elem: A)ListBuffer.this.type

    Remove a single element from this buffer.

  3. def-=(elem1: Aelem2: Aelems: A*)ListBuffer.this.type

    Removes two or more elements from this shrinkable collection.



스칼라 2.11로 테스트 해보면 다음과 같다. 


scala> import scala.collection.mutable.ListBuffer

import scala.collection.mutable.ListBuffer


scala> var thrill = new ListBuffer[String]()

thrill: scala.collection.mutable.ListBuffer[String] = ListBuffer()


scala> thrill += "aaa"

res0: scala.collection.mutable.ListBuffer[String] = ListBuffer(aaa)


scala> thrill += "bbb"

res1: scala.collection.mutable.ListBuffer[String] = ListBuffer(aaa, bbb)


scala> thrill.filter(s => s.length == 2)

res4: scala.collection.mutable.ListBuffer[String] = ListBuffer()


scala> thrill.filter(s => s.length == 3)

res5: scala.collection.mutable.ListBuffer[String] = ListBuffer(aaa, bbb)


scala> thrill.remove(1)

res6: String = bbb


scala> thrill -= "bbb"

res7: scala.collection.mutable.ListBuffer[String] = ListBuffer(aaa)

Posted by '김용환'
,

scala + scalatra + gradle

scala 2015. 11. 30. 20:58


scala + spring boot + gradle 조합이 안좋아서, 


scala + scalatra + gradle을 테스트해보려고 한다.


템플릿은 https://github.com/hermansc/scalatra-gradle-helloworld 를 포크해서 

https://github.com/knight1128/scalatra-gradle-helloworld 를 만들었다.


(근데, gradle pluging인 greety의 주 개발자가 더 이상 활동을 안하고 있다..)

Posted by '김용환'
,


scalatra의 scalate 사용시 아래와 같은 에러가 발생했다.



Caused by: java.lang.NoSuchMethodError: scala.tools.nsc.Global$gen$.mkBlock(Lscala/collection/immutable/List;)Lscala/reflect/internal/Trees$Tree;scala.tools.nsc.Global$gen$.mkBlock(Lscala/collection/immutable/List;)Lscala/reflect/internal/Trees$Tree;




https://groups.google.com/forum/#!topic/scalatra-user/WGJrzzGYlHA 의 조언("Scalate embeds the compiler, which is not binary compatible across Scala point releases."대로 scala-reflect와 scala-compiler를 dependency에 명시하니 더이상 에러가 발생되지 않았다.


dependencies {
compile "org.scala-lang:scala-library:2.11.7"
compile "org.scala-lang:scala-reflect:2.11.7"
compile "org.scala-lang:scala-compiler:2.11.7" }



Posted by '김용환'
,


scala + spring boot + gradle 연동시 cool swapping 되게 하는 팁이다.


0. intellij idea 먼저 scala plugin을 설치한다.



1. 터미널

# ./gradlew bootRun


소스 수정하면 자동으로 spring boot devtools에 의해 cool swapping된다.

(만약 자동 재시작이 되지 않으면, ./gradlew compileScala 를 실행한다.)




2. Intellij 에서 spring boot 실행시켜 사용하기

실행은 gradlew의 bootRun을 실행한다. 


오후 8:47:53: Executing external task 'bootRun'...

:processResources UP-TO-DATE
:classes
:findMainClass
:bootRun

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::  (v1.3.0.BUILD-SNAPSHOT)
...

 소스 수정 후, 매번 사람 손으로 Intellij idea의 Build -> Make Project (%F9)를 선택해야 한다.




3. Intellij 에서 spring boot 실행시키고 custom macro + key map 연동 사용하기 (강추)

idea에서 소스 변경하여 저장할 때마다 컴파일이 안되서, macro를 사용한다. idea는 매크로를 지원한다. 

매크로를 추가한다.

Edit -> Macros -> Start Macro Recording 

Build -> Make Project 선택

Edit -> Macros -> Stop Macro Recording 



매크로의 이름을 compileScala로 저장했다.



제대로 저장했는지 확인한다. 




macro롤 key map에 바인딩한다. 




Macros -> Add keyboard에 커서를 두고 마우스 오른쪽 버튼을 눌러 Add Keyboard Shortcut을 선택하고 저장 쇼컷(Command + s)를 누른다.


ok 버튼을 누르고 다이얼로그 창을 모두 내린다. 

intellij idea에서 소스를 수정하고 Command + s를 눌러본다. devtools가 제대로 작동하는지 확인할 수 있다.



참조 : https://www.jetbrains.com/idea/help/accessing-settings.html



추가

intellij 15로 업그레이드 하다가 아래와 같은 에러가 발생했다.
Warning:scala: skipping Scala files without a Scala SDK in module(s) project-name

 기존 scala 정보를 못쓰고 있었을 수 있다. setup Scala SDK를 살펴보고 올바르게 설정하면 더이상 문제가 발생하지 않는다.


Posted by '김용환'
,

scala + spring boot + gradle

scala 2015. 10. 19. 17:39


scala + spring boot + gradle 프로젝트를 진행하려고 하는데, 좋은 예제가 github에 있었다.


https://github.com/bijukunjummen/spring-boot-scala-web




이를 scala 2.11.7, spring boot 1.3, gradle 2.7에 맞게 수정해서 github에 올렸으니, 참고하면 좋을 듯하다.


https://github.com/knight1128/spring-boot-scala-web

Posted by '김용환'
,


scala 2.11.7 & springboot 1.3.0 SNAPSHOT & gradle을 사용하고 있으며, java.lang.VerifyError: class com.fasterxml.jackson.module.scala.ser.ScalaIteratorSerializer overrides final method withResolved.

빌드시 다음과 같은 에러가 발생했다. 



     java.lang.VerifyError: class com.fasterxml.jackson.module.scala.ser.ScalaIteratorSerializer overrides final method withResolved.(Lcom/fasterxml/jackson/databind/BeanProperty;Lcom/fasterxml/jackson/databind/jsontype/TypeSerializer;Lcom/fasterxml/jackson/databind/JsonSerializer;)Lcom/fasterxml/jackson/databind/ser/std/AsArraySerializerBase;


원인은 scala jackson 모듈 컴파일시 withResolved 메소드 구현 이슈로 verify error가 발생했다.


scala jackson module(정확히 말하면 jackson-databind 2.6) 에서 새로운 api가 정의되었고, 이를 제대로 연동이 안되는 문제가 발생했다.

public abstract AsArraySerializerBase<T> withResolved(BeanProperty property,

        TypeSerializer vts, JsonSerializer<?> elementSerializer,

        Boolean unwrapSingle);



참고 자료 : https://github.com/FasterXML/jackson-module-scala/issues/214



gradle dependencies로 보면, spring boot 1.3.0 snapshot 빌드 버전의 jackson-databind 버전은 2.6.1 이다. 


     

\--- com.fasterxml.jackson.module:jackson-module-scala_2.10:2.3.1

     +--- org.scala-lang:scala-library:2.10.2 -> 2.11.5

     +--- com.fasterxml.jackson.core:jackson-core:2.3.1 -> 2.6.1

     +--- com.fasterxml.jackson.core:jackson-annotations:2.3.0 -> 2.6.1

     +--- com.fasterxml.jackson.core:jackson-databind:2.3.1 -> 2.6.1 (*)

     +--- com.thoughtworks.paranamer:paranamer:2.6

     +--- com.google.code.findbugs:jsr305:2.0.1

     \--- com.google.guava:guava:13.0.1

     

spring boot 1.2.6.RELEASE 버전으로는 정상적으로 spring boot가 실행되는데, jackson-databind 버전은 2.4.0 이다.

     


\--- com.fasterxml.jackson.module:jackson-module-scala_2.10:2.3.1

     +--- org.scala-lang:scala-library:2.10.2 -> 2.11.5

     +--- com.fasterxml.jackson.core:jackson-core:2.3.1 -> 2.4.6

     +--- com.fasterxml.jackson.core:jackson-annotations:2.3.0 -> 2.4.0

     +--- com.fasterxml.jackson.core:jackson-databind:2.3.1 -> 2.4.6 (*)

     +--- com.thoughtworks.paranamer:paranamer:2.6

     +--- com.google.code.findbugs:jsr305:2.0.1

     \--- com.google.guava:guava:13.0.1

     

     

그래서, jackson version을 2.4.x로 바꿔봤더니. 잘 동작된다. 


def jacksonVersion = '2.4.4'

configurations {
all*.exclude module : 'com.fasterxml.jackson.core:jackson-databind'
all*.exclude module : 'com.fasterxml.jackson.core:jackson-core'
all*.exclude module : 'com.fasterxml.jackson.core:jackson-annotations'
}

dependencies { //..

compile "com.fasterxml.jackson.core:jackson-core:${jacksonVersion}"
compile "com.fasterxml.jackson.core:jackson-databind:${jacksonVersion}"
compile "com.fasterxml.jackson.core:jackson-annotations:${jacksonVersion}" }

     

 







Posted by '김용환'
,



play2에서 Schedule작업을 하려면, Akka를 써야 한다.


https://www.playframework.com/documentation/2.2.x/ScalaAkka


단점이 하나 있는데, 주기만 있지 cron expression을 지원하지 않는다.

따라서, cron을 쓰려면 quartz java lib을 써야 한다. (이거 참 불편했다.)


import play.api.libs.concurrent.Execution.Implicits._
Akka.system.scheduler.schedule(0.microsecond, 300.microsecond, testActor, "tick")


import play.api.libs.concurrent.Execution.Implicits._
Akka.system.scheduler.scheduleOnce(1000.microsecond) {
  file.delete()
}





반면, play1에서는 play.jobs.Job을 상속한 클래스에서 annotation을 쓰면 되며, cron expression도 된다. 애플리케이션 시작할 때도 사용할 수 있다.. 


https://www.playframework.com/documentation/1.1/jobs



@On("0 0 12 * * ?")

@Every("1h")

@Every("1min")

@OnApplicationStart


Posted by '김용환'
,


java 개발하듯이 -D 옵션으로 jmx를 추가하면 jmx 포트가 열린다. jconsole, jvisualvm을 쓸 수 있다.  


localhost, remote 모두 잘 연결된다.



$ activator run -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=10100 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false


Posted by '김용환'
,


java의 Rabbitmq client library의 DefaultConsumer를 그냥 상속하면 다음 에러가 발생한다. 



not enough arguments for constructor DefaultConsumer: (x$1: com.rabbitmq.client.Channel)com.rabbitmq.client.DefaultConsumer.


[error] Unspecified value parameter x$1.

[error] class Worker extends DefaultConsumer {

[error]                      ^

[error] one error found

[error] (compile:compile) Compilation failed



그 이유는 DefaultConsumer의 첫번째 아규먼트 인수를 무조건 받는 생성자를 가지고 있기 때문이다. 


public class DefaultConsumer implements Consumer {

    /** Channel that this consumer is associated with. */

    private final Channel _channel;

    /** Consumer tag for this consumer. */

    private volatile String _consumerTag;


    public DefaultConsumer(Channel channel) {

        _channel = channel;

    }


Scala에서는 아래와 같이 구현한다. 에러도 안나고, bolierplate 코드도 조금 없어지는 느낌이다. 



class Worker(ch: Channel) extends DefaultConsumer(ch) {

  val channel : Channel = ch

...


}


Posted by '김용환'
,

scala (activator) 사용 팁

scala 2014. 12. 9. 01:26


scala 최신 버전 (2.11)부터는 type safe사(제임스 고슬링이 고문으로 참여)의 activator가 추가된 버전을 사용할 수 있다.
특히 play2 scala 버전에서도 activator를 잘 사용하고 있다.

play1 에서 $play run 실행 처럼 play2에서는 $activator run 실행하면 play가 실행된다.


또한 test는 $activator test 실행하면 play 테스트가 실행된다.

그외에도. 

$activator test-quick (기존의 실패한 것만 실행)

$activator new (play2 스칼라 버전 기본 템플릿[아키타입] 다운받기) 

$activator shell (cli)


* 참고 내용

http://typesafe.com/activator/template/hello-scala-2_11

https://typesafe.com/blog/typesafe-activator-what-is-it

http://rosslawley.co.uk/posts/typesafe_activator/

Posted by '김용환'
,