読者です 読者をやめる 読者になる 読者になる

t.marcusの外部記憶装置

忘備録とかちょっとした考えとかをつらつらと...

Spring + JUnitでParameterized実行する

qiita.com

上記のQiita記事通りにやっても動かなかったので…

以下のような感じで、@ClassRuleと@Ruleを宣言してやれば無事動いた

package org.tmarcus

import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.test.context.junit4.rules.SpringClassRule;
import org.springframework.test.context.junit4.rules.SpringMethodRule;

@ActiveProfiles("test")
@SPringApplicationConfiguration(ParameterizedTestBase.class)
@EnableAutoConfiguration
@ComponentScan(basePackages = {
  "org.tmarcus"
})
@RunWith(Parameterized.class)
public ParameterizedTestBase extends TestBase {
  
  @ClassRule
  public static final SpringClassRule SCR = new SpringClassRule();

  @Rule
  public final SpringMethodRule springMethodRule = new SpringMethodRule();

}
package org.tmarcus

import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runners.Parameterized;
import org.tmarcus.service.MathmaticsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.TestContextManager;

import java.util.Collection;
import java.util.List;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

@Slf4j
public class SampleTest extends ParameterizedTestBase {

  private MathmaticsService service;

  @Autowired
  public void inject(
      MathmaticsService service) {
    this.service = service;
  }

  @Parameterized.Parameters
  public static Collection<Object[]> data() {
    return Arrays.asList(new Object[][] {
      { 0, 1 },
      { 1, 1 },
      { 2, 2 },
      { 3, 6 },
      { 4, 24 },
      { 5, 120 }
    });
  }

  @Parameterized.Parameter(0)  // <- index=0のパラメータを代入する
  public int parameter;

  @Parameterized.Parameter(1)  // <- index=1のパラメータを代入する
  public int factorialExpected;

  @Test
  public void test() {
    log.info("{} -> {}", parameter, expected);
    assertThat(service.factorial(parameter), is(factorialExpected));
  }
}

Angular.js (v1系) vs textarea

Angular.jsでtextareaの高さを自動で可変するやつ。

gist.github.com

もうちょっといいやり方無いかなぁ…

RabbitMQでHAを利用したときにClientで例外を吐いてしまう問題

RabbitMQでClusterを組み、ミラーリングを設定して、いざクライアントからデータを流そうとしたら、下記のようなエラーが出てキューを開けなかったので、その対応方法の覚書。

Caused by: com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method<channel.close>(reply-code=406, reply-text=PRECONDITION_FAILED - inequivalent arg 'x-ha-policy'for queue 'queue_name01ha' in vhost '/': received none but current is the value 'all' of type 'longstr', class-id=50, method-id=10)
        at com.rabbitmq.utility.ValueOrException.getValue(ValueOrException.java:67)
        at com.rabbitmq.utility.BlockingValueOrException.uninterruptibleGetValue(BlockingValueOrException.java:33)
        at com.rabbitmq.client.impl.AMQChannel$BlockingRpcContinuation.getReply(AMQChannel.java:361)
        at com.rabbitmq.client.impl.AMQChannel.privateRpc(AMQChannel.java:226)
        at com.rabbitmq.client.impl.AMQChannel.exnWrappingRpc(AMQChannel.java:118)
        ... 67 common frames omitted
Caused by: com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method<channel.close>(reply-code=406, reply-text=PRECONDITION_FAILED - inequivalent arg 'x-ha-policy'for queue 'queue_name01ha' in vhost '/': received none but current is the value 'all' of type 'longstr', class-id=50, method-id=10)
        at com.rabbitmq.client.impl.ChannelN.asyncShutdown(ChannelN.java:484)
        at com.rabbitmq.client.impl.ChannelN.processAsync(ChannelN.java:321)
        at com.rabbitmq.client.impl.AMQChannel.handleCompleteInboundCommand(AMQChannel.java:144)
        at com.rabbitmq.client.impl.AMQChannel.handleFrame(AMQChannel.java:91)
        at com.rabbitmq.client.impl.AMQConnection$MainLoop.run(AMQConnection.java:560)
        ... 1 common frames omitted

Channelでキューを宣言するときに、このメソッドの第六引数で、以下の通りHAを使うという設定を入れてやればOK。

Connection connection = connectionFactory.getConnection();
Channel channel = connection.createChannel();
Map<String, Object> arguments = Maps.newHashMap();
arguments.put("x-ha-policy", "all");
channel.queueDeclare("queue_name01ha", true, true, false, false, arguments);

SpringMVCのMockMvcでurlVariablesを使う方法

SpringMVCのテストを書くときによく使うMockMvcで指定するgetやらpostやらでurlTemplate内でurlVarsをどう指定すればドキュメントが見当たらなかったので、ソースに潜った結果、どうすればいいかの覚書

第2引数をindex=0として{index}という形で書いてやれば置換される模様

例)

server.perform(get("/user/{0}/{1}/setting/categories", idType.getCode(), id)
		.header(HttpHeaders.CONTENT_TYPE, MEDIA_TYPE_APPLICATION_JSON))
		.andExpect(status().isOk())

server.perform(post("/user/{0}/{1}/setting/category/{2}", idType.getCode(), id, CATEGORY1)
		.header(HttpHeaders.CONTENT_TYPE, MEDIA_TYPE_APPLICATION_JSON))
		.andExpect(status().isOk())

Javaライブラリ覚書

MVC Framework

github.com

github.com

github.com

DI

github.com

Http

github.com

github.com

Utilities

github.com

github.com

github.com

github.com

JMX

github.com

Nexus Repository Managerにファイルを直接アップロードする

こんな感じで、個別にアップロードできるらしい。

$ curl -v \
  -u ${NEXUS_USER}:${NEXUS_PASS} \
  --upload-file hoge-api-server-sources.jar \
  http://nexus.example.com/content/repositories/releases/com/example/hoge-api-server/1.10.0/hoge-api-server-1.10.0-sources.jar

maven-release-pluginでReceived fatal alert: bad_record_macが出た話

リリース作業中に問題発生したので、自戒録がてら書き連ねておく。

結果としては、Java7だったので、MAVEN_OPTS="-Dhttps.protocols=TLSv1,TLSv1.1,TLSv1.2"環境変数にぶち込んで走らせれば解決しました。
(Java8は試してませんが、おそらく-Dhttps.protocols=TLSv1,TLSv1.1,TLSv1.2 -Djdk.tls.client.protocols=TLSv1,TLSv1.1,TLSv1.2を指定すれば、行けるはずです)


事の起こりは、リリース作業中にpomのバージョンをイテレーションして、Sonatype Nexus Repository Manager(以下、Nexus)へ成果物のアップロードを行うJenkinsジョブを実行したところ…

f:id:t_marcus87:20160209193850p:plain

_人人人人人人人人人人人人人人_
> 燦々と輝く「ジョブ失敗」 <
 ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y ̄

とりあえず、ログを眺めてみると…

$ mvn -Dresume=false release:prepare release:perform -B
:
:
[INFO] --- maven-release-plugin:2.0:prepare (default-cli) @ hoge-api-server ---
:
:
[INFO] --- maven-release-plugin:2.0:perform (default-cli) @ hoge-api-server ---
:
:
[INFO] [INFO] --- maven-deploy-plugin:2.7:deploy (default-deploy) @ hoge-api-server ---
[INFO] Uploading: https://nexus.example.com/content/repositories/releases/com/example/api/hoge-api-server/1.59.0/hoge-api-server-1.59.0.jar
[INFO] Uploading: https://nexus.example.com/content/repositories/releases/com/example/api/hoge-api-server/1.59.0/hoge-api-server-1.59.0.pom
[INFO] Uploaded: https://nexus.example.com/content/repositories/releases/com/example/api/hoge-api-server/1.59.0/hoge-api-server-1.59.0.pom (9 KB at 28.9 KB/sec)
[INFO] [INFO] ------------------------------------------------------------------------
[INFO] [INFO] BUILD FAILURE
[INFO] [INFO] ------------------------------------------------------------------------
[INFO] [INFO] Total time: 53.752s
[INFO] [INFO] Finished at: Tue Feb 09 13:31:27 JST 2016
[INFO] [INFO] Final Memory: 57M/1313M
[INFO] [INFO] ------------------------------------------------------------------------
[INFO] [ERROR] Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy (default-deploy) on project hoge-api-server: Failed to deploy artifacts: Could not transfer artifact com.example:hoge-api-server:jar:1.10.0 from/to hoge-releases (https://nexus.hoge.org/content/repositories/releases/): Received fatal alert: bad_record_mac -> [Help 1]
[INFO] [ERROR] 
[INFO] [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[INFO] [ERROR] Re-run Maven using the -X switch to enable full debug logging.
[INFO] [ERROR] 
[INFO] [ERROR] For more information about the errors and possible solutions, please read the following articles:
[INFO] [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException

何やら、Nexusへの登録がbad_record_macで失敗してるっぽい。

とりあえず、ググってみる

検索結果から、SSL周りのエラーっぽい雰囲気が漂ってくる。

とりあえずjenkinsサーバに入って、Nexusと話をしてみる…

$ curl -vs https://nexus.example.com
* Rebuilt URL to: https://nexus.example.com/
*   Trying 12.34.56.78...
* Connected to nexus.example.com (12.34.56.78) port 443 (#0)
* TLS 1.2 connection using TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
* Server certificate: *.example.com
:
:
> GET / HTTP/1.1
> Host: nexus.example.com
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: text/html
< Content-Length: 8009
< Connection: keep-alive
< X-Frame-Options: SAMEORIGIN
< X-Content-Type-Options: nosniff
< Last-Modified: Tue, 09 Feb 2016 10:47:55 GMT
< Pragma: no-cache
< Cache-Control: post-check=0, pre-check=0
< Expires: 0
<
<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
:
:

ちゃんとお話できてるっぽい。

SSLといえば、最近Poodleの関係で、SSLv3がサポート切られてたりしてたはず…ということで、SSLv3でお話してみると…

$ curl -vs --sslv3 https://nexus.example.com
* Rebuilt URL to: https://nexus.example.com/
*   Trying 12.34.56.78...
* Connected to nexus.example.com (12.34.56.78) port 443 (#0)
* SSL peer handshake failed, the server most likely requires a client certificate to connect
* Closing connection 0
curl: (35) SSL peer handshake failed, the server most likely requires a client certificate to connect

ビンゴ!

ということで、Javaのオプションで、SSLv3をオフって解決

mvn -Dhttps.protocols=TLSv1,TLSv1.1,TLSv1.2 -Dresume=false release:prepare release:perform -B

詳しくはこちら