[開発] Thymeleaf Quick Reference - Sample Codes

ThymeleafQuickReferenceApplication.java
package hoge;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.stereotype.Controller;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@SpringBootApplication
@Controller
public class ThymeleafQuickReferenceApplication extends WebMvcConfigurerAdapter {

  public static void main(String[] args) throws Exception {
    new SpringApplicationBuilder(Application.class).run(args);
  }

}

ThymeleafQuickReferenceController.java

package hoge.app.welcome;

import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import lombok.Data;

/**
* Handles requests for the application home page.
*/
@Controller
public class ThymeleafQuickReferenceController {

  private static final Logger logger = LoggerFactory.getLogger(ThymeleafQuickReferenceController.class);

  /**
   * Simply selects the home view to render by returning its name.
   */
  @RequestMapping(value = "/", method = { RequestMethod.GET, RequestMethod.POST })
  public String home(Locale locale, Model model) {
    logger.info("Welcome home! The client locale is {}.", locale);

    Date date = new Date();
    DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);

    String formattedDate = dateFormat.format(date);

    model.addAttribute("serverTime", formattedDate);

    return "welcome/home";
  }

  @GetMapping("/actionPath")
  public String dispItemList(Model model, HttpServletRequest request, @RequestParam("paramName") String varName) {
    // HTTP Headers --------------------
    Map<'String, String> httpHeaderMap = new HashMap<'String, String>();
    Enumeration headerNames = request.getHeaderNames();
    while (headerNames.hasMoreElements()) {
      String key = (String) headerNames.nextElement();
      String value = request.getHeader(key);
      System.out.println(key + ":" + value);
      httpHeaderMap.put(key, value);
    }

    // String userName = request.getUserPrincipal().getName();

    ActionForm form = new ActionForm();
    List<'Item> itemList = new ArrayList<'Item>();// 項目一覧;
    Set<'String> itemGroupNameSet = new LinkedHashSet<'>();

    List<'Map<'String, Object>> queryResult = queryItemList();
    
    for (Map row : queryResult) {
      Item item = new Item();
      item.setId(Integer.parseInt(row.get("col_item_id").toString()));
      String itemGrpName = String.valueOf(row.get("col_item_grp_name"));
      item.setItemGrpName(itemGrpName);
      item.setItemName(String.valueOf(row.get("col_item_name")));
      item.setItemDisc(String.valueOf(row.get("col_item_disc")));
      item.setCurrentHogeCount(Integer.parseInt(row.get("col_cur_hoge_cnt").toString()));
      item.setTargetHogeCount(Integer.parseInt(row.get("col_tar_hoge_cnt").toString()));
      item.setHogePercent(String.valueOf(row.get("col_hoge_pcnt").toString()));
      item.setSelectedValue("1");
      itemGroupNameSet.add(itemGrpName);
    }
    form.setItemGroupNameSet(itemGroupNameSet);
    form.setItemList(itemList);
    model.addAttribute(form);
    return "thymeleafQuickReference";
  }

  private List<'Map<'String, Object>> queryItemList() {
    // TODO Auto-generated method stub
    return null;
  }

  public @Data class Item {
    int id;
    String itemGrpName;
    String itemName;
    String itemDisc;
    int currentHogeCount;
    int targetHogeCount;
    String hogePercent;
    String selectedValue;

    @Override
    public String toString() {
      String str =
          "itemName: " + itemName + "\n" +
          "itemDisc: " + itemDisc + "\n" +
          "currentHogeCount: " + currentHogeCount + "\n" +
          "";
      return str;
    }
  }
  
  public @Data class ActionForm {
    Set<'String> itemGroupNameSet;
    List<'Item> itemList;
    
  }
}

■ thymeleafQuickReference.html
<'!DOCTYPE html>
<'html xmlns:th="http://www.thymeleaf.org" lang="ja">

<'head>
<'!-- Required meta tags -->
<'meta charset="utf-8"><'/meta>
<'meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"><'/meta>

  <'!-- Title -->
  <'title>Page Title<'/title>

<'!-- Bootstrap CSS
<'link rel="stylesheet" th:href="@{/css/bootstrap.min.css}" href="../../css/bootstrap.min.css" /> TBC -->
<'link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css"/>

  <'!-- Page Original Styles -->
  <'!-- jQuery Read More/Less Toggle - A PEN BY Max (https://codepen.io/maxds/pen/jgeoA) -->

  <'style type="text/css">
  * {
    font-family: "Meiryo UI";
    color: #555;
    /* border: 1px solid navy; */
  }
  html, body{
    width:100%;
    height:100%;
  }
  .morecontent span {
    display: none;
  }
  .morelink {
    display: block;
  }
  <'/style>  
<'/head>
<'body>

<'!-- ============================================================ -->

<'form th:action="@{/actionPath}" method="post" th:object="${actionForm}">
<'input type="hidden" th:value="*{valFromSvr1}" name="valName1" />
<'input type="hidden" th:value="*{valFromSvr2}" name="valName2" />

<'!-- 固定ページヘッダ -->
<'nav class="navbar navbar-default navbar-fixed-top">
  <'div class="container-fluid">
    <'div class="navbar-header">
      <'a class="navbar-brand" href="#"><'span style="white-space: nowrap; font-size: x-large">
        <'img alt="logo" src="img/logo.png" style="height: 25px;"/>
        論理ページ名
      <'/span><'/a>
    <'/div>
    <'div class="collapse navbar-collapse">
      <'p class="navbar-text navbar-right" style="padding-right: 20px">
        ようこそ <'a href="#" class="navbar-link">ゲスト<'/a> さん | <'a th:href="@{/}" href="home.html" class="btn btn-outline-primary"> ホーム<'/a>
      <'/p>
    <'/div>
  <'/div>
  <'div class="container-fluid" style="font-size: large; padding-bottom: 10px;">
  ページ紹介文
   <'span class="label label-default">レベル1<'/span> <'span th:text="*{valFromSvr3}" style="font-weight: bold; color: crimson;"><'/span>日
  <'span th:if="!*{hasDone()}">
  <'!-- 処理未完時はsubmitボタンを表示する -->
     <'input type="submit" value="送信" class="btn-xs btn-primary"/>
  <'/span>
  <'/div>
<'/nav>

<'!-- ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ -->

<'div style="margin: 100px 20px 0px 20px; overflow-y: auto">

read more/less sample
<'span class="more">
ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ
<'/span>

<'div class="panel-group" id="sampleAccordion">
  <'!-- // アイテムグループブロック -->
  <'div class="panel panel-default" th:each="itemGrpName,itemGrpNameStat : *{itemGrpNameSetFromSvr}">
    <'div class="panel-heading">
      <'h3 class="panel-title">
        <'a data-toggle="collapse" data-parent="#sampleAccordion" th:href="'#accordionCollapse' + ${groupName}">
          <'!-- アイテムグループ名 -->
          <'h4 th:text="${itemGrpName}"><'/h4>
        <'/a>
      <'/h3>
    <'/div>
    <'div th:id="'accordionCollapse' + ${groupName}" class="panel-collapse collapse in">
      <'div class="panel-body">
        <'!-- // アイテムグループ別テーブル -->
        <'table class="table table-hover" style="width:100%;" th:each="item,rowStat : *{itemList}" th:if="${item.funcGrpName} == ${itemGrpName}">
          <'tbody>
            <'!-- // アイテム行 -->
            <'tr><'td>
              <'!-- // アイテム別詳細掲載テーブル -->
              <'table style="width:100%;">
                <'tbody>
                  <'tr>
                    <'!-- // アイテム見出し -->
                    <'td style="width:20%;">
                      <'!-- アイテム名 -->
                      <'h4 th:text="${item.itemName}"><'/h4>
                    <'/td>
                    <'td style="width:55%; ">
                      <'!-- // statusbar -->
                      <'div class="progress" style="margin-top: 24px; ">
                        <'div class="progress-bar" role="progressbar" th:style="'width: ' + ${item.hogePercent}+'%;'"><'!-- 獲得数比率 -->
                          <'span th:text="${item.currentHogeCount}" style="color: white;"><'/span><'!-- 獲得数 -->
                        <'/div>
                      <'/div>
                      <'!-- statusbar // -->

                    <'/td>
                    <'td style="width:10%; padding: 2px">
                      <'span class="label label-success" th:if="${item.hogePercent}==100" th:text="'達成'"><'/span>
                      <'span class="label label-default" th:if="${item.hogePercent}<100" th:text="'達成まであと'+${item.targetHogeCount-item.currentHogeCount}+'!'"><'/span>
                    <'/td>
                    <'!-- アイテム見出し // -->
                    <'td th:if="!*{hasDone()}" th:each="radioButton : *{radioButtons()}" rowspan="2" style="width:7%; text−align: center; padding: 10px;">
                      <'input type="radio" th:field="*{itemList[__${rowStat.index}__].selectedValue}" th:value="${radioButton.key}" />
                      <'label th:for="${#ids.next('selectedValue')}" th:text="${radioButton.value}"><'/label>
                    <'/td>
                  <'/tr>
                  <'tr>
                    <'td colspan="3">
                      <'!-- アイテム説明 -->
                      <'span class="more" th:text="${item.itemDisc}">
                      <'/span>
                    <'/td>
                  <'/tr>
                <'/tbody>
              <'/table>
              <'!-- アイテム別詳細掲載テーブル // -->
            <'/td><'/tr>
            <'!-- アイテム行 // -->
          <'/tbody>
        <'/table>
        <'!-- アイテムグループ別テーブル // -->
      <'/div>
    <'/div>
  <'/div>
  <'!-- アイテムグループブロック // -->
<'/div>

<'/div>
<'/form>
<'!-- ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ -->

<'div align="right">
  <'form th:action="@{/logout}" method="post"><'input type="submit" value="ログアウト"/><'/form>
<'/div>

<'!-- ============================================================ -->

  <'script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"><'/script>
  <'script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"><'/script>

  <'!-- js for read more/less -->
  <'script type="text/javascript">
  $(document).ready(function() {
    // Configure/customize these variables.
    var showChar = 50; // How many characters are shown by default
    var ellipsestext = "...";
    var moretext = "Show more >";
    var lesstext = "Show less";
    

    $('.more').each(function() {
      var content = $(this).html();
  
      if(content.length > showChar) {
        // disp ShowMore
        var c = content.substr(0, showChar);
        var h = content.substr(showChar, content.length - showChar);//content for hiding
  
        var html = c + '<'span class="moreellipses">' + ellipsestext+ ' <'/span><'span class="morecontent"><'span>' + h + '<'/span>  <'a href="" class="morelink">' + moretext + '<'/a><'/span>';

        $(this).html(html);
      }
  
    });
  
    $(".morelink").click(function(){
      if($(this).hasClass("less")) {
        $(this).removeClass("less");
        $(this).html(moretext);
      } else {
        $(this).addClass("less");
        $(this).html(lesstext);
      }
      $(this).parent().prev().toggle();
      $(this).prev().toggle();
      return false;
    });
  });
  <'/script>
<'/body>
<'/html>

tag : Thymeleaf Quick Reference Sample Codes

2017-09-17 08:59 : 開発 : コメント : 0 : トラックバック : 0 :

[開発][DB][H2] H2DBの永続化

インメモリDBH2データを永続化する


tag.
Spring H2 DB 永続化 インメモリ

ref.
Spring Boot お勉強 その3 ~H2DB永続化
http://yosshio0426.hatenadiary.com/entry/2014/07/21/070153
Common application properties
https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#common-application-properties

tag : Spring H2 DB 永続化 インメモリ java

2017-09-17 08:52 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] getter/setterが煩わしいのでロンボックを入れる

close STS
https://projectlombok.org/download
exe jar
start STS
rebuild project

ref.
Eclipse:lombokインストール手順
http://web-dev.hatenablog.com/entry/eclipse/lombok

tag : sts lombok eclipse java

2017-09-17 08:50 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] GitBash で GitHub から project を clone する

■ 初期設定
exe GitBash
$ cd /c/myfolder/_git
$ git init
$ git config --global user.name hogehoge
設定値の確認
$ git config --global --list
$ git config user.name

$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.com
$ git config --global color.ui auto

設定値の保存先
$HOMEディレクトリ ― C:\Documents and Settings\$USER か C:\Users\$USER
e.g.
C:\Users\Administrator\git
C:\Program Files\Git\etc

ref.
GitHubでユーザ名・パスワード省略(push, pull)
http://qiita.com/azusanakano/items/8dc1d7e384b00239d4d9
特定のGitリポジトリだけAuthorを変更する
http://qiita.com/sasaplus1/items/a12e95aa234139f1f8f7



■ サンプルアプリ
$ git clone git://github.com/SpringSource/spring-mvc-showcase.git
$ cd spring-mvc-showcase
$ mvn tomcat7:run [-Dmaven.tomcat.port=] (In case 8080 is busy]
Access the deployed web application at: http://localhost:8080/spring-mvc-showcase/

$ git clone https://github.com/spring-projects/spring-petclinic.git
$ cd spring-petclinic
$ ./mvnw spring-boot:run

access petclinic here: http://localhost:8080/

note:
fork(フォーク) GitHubの機能の1つで、GitHubにある他の開発者のリポジトリをGitHub上でcloneすること

ref.
https://github.com/spring-projects/spring-petclinic
https://github.com/spring-projects/spring-mvc-showcase
https://github.com/spring-projects/spring-boot/tree/master/spring-boot-samples

tag : git github clone fork GitBash

2017-09-17 08:49 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] Apache Maven を install する

JDK* and JAVA_HOME
http://www.oracle.com/technetwork/java/javase/downloads/index.html
Java Platform (JDK) 8u144
for 32bit env >> 「x64」ではなく「x86 (jdk-7u75-windows-i586.exeなど)」を選択すること
* Java Development Kit (32 bit)
ref.
WindowsにJDK7をインストールする
http://qiita.com/zonoscript/items/b8999267295bd9e442b1

download
http://maven.apache.org/download.cgi
apache-maven-3.5.0-bin.zip

unzip/save
C:\Program Files\Apache\maven
├bin/boot/conf/lib
└LICENSE/NOTICE/README.txt

Add M2_HOME and MAVEN_HOME
M2_HOME: C:\Program Files\Apache\maven
MAVEN_HOME: C:\Program Files\Apache\maven

Add To PATH:
%M2_HOME%\bin

Verification
C:\Users\hoge>mvn -version
Apache Maven 3.2.2...
Maven home: C:\Program Files\Apache\maven...
C:\Users\hoge>


ref.
How to install Maven on Windows, By mkyong | November 25, 2009
https://www.mkyong.com/maven/how-to-install-maven-in-windows/

tag : Apache Maven MAVEN_HOME M2_HOME

2017-09-17 08:47 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] STS に Git プロジェクトを import する

// SSH鍵設定が出来ていればコレ↓でimportできる
STS v3.9.0 (eclipse v4.7.0)
Package Explorer
Context Menu
Import
Maven > Check out Maven Projects from SCM
SCM URL: git: https://github.com/jxia1268/hoge-project
Finish

// SSH鍵の生成
PuTTY Key Generator
Parameters: Type of key to generate: SSH-2RSA
Actions > Generate
Save C:\_putty\id_rsa.pub -- public key
Save C:\_putty\id_rsa.ppk -- private key

tag.
STS Git eclipse import project
ref.
gitのプロジェクトをEclipseでインポートする
http://d.hatena.ne.jp/mintsu123/20140303/1393857425
PuTTYで公開鍵認証方式でのSSH接続を行う手順まとめ
http://qiita.com/sugar_15678/items/55cb79d427b9ec21bac2

tag : Git GitHub STS SSH Maven PuTTY eclipse

2017-09-17 08:45 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] ライセンスいろいろ

tag: license GPL LGPL BSD MIT MPL CC

「無料素材」に「フリーソフト」、何でも無料で手に入るが
「使用料金が無料なだけ」であって、「完全に自由に使用する事が可能ではない」
全てライセンス(使用許諾条件)に添った形で配布・提供されており
著作権を有する制作者本人が示す使用許諾条件を守る事は、
制作者への敬意であると同時に、意図しない「著作権の侵害」を未然に防ぐ手段

■ All Rights Reserved
 「すべての著作権は作成者自身が保有します」
 無断で使用することは一切出来ない

GPL(GNU General Public License)
 著作権表示をすること
 作成者は責任を負わない(無保証)
 ソースコードを公開すること
 自由に改修OK
 GPLv3のソースコードを組み込んだソースコードはGPLv3で公開すること (商用の場合は提供先に対して公開する)

LGPL(GNU Lesser General Public License)
BSD(Berkeley Software Distribution License)

MIT License(X11 License、X Licenseとも呼ばれる)
 勝手に使っていいし、商用利用もOK
 MIT Licenseのxxxというソースコードを取り込んでいますよと表示すること

MPL(Mozilla Public License)
CC(Creative Commons)
■ public domain


ref.
GPLやMITCCなど主要ライセンスの内容と意味のまとめ
http://smkn.xsrv.jp/blog/2009/03/summary_for_gpl_mit_cc_etc/
MIT?GPL?ライセンスって何ぞ?jsdo.itから学ぶライセンス入門
http://akiok-jp.hatenablog.com/entry/2013/04/06/222243

tag : license GPL LGPL BSD MIT MPL CC ライセンス

2017-09-12 00:43 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] 今更ながらのWebフロント技術の勉強 - Bootstrap

bootstrap

css framework
getbootstrap.com
required: HML/CSS/JavaScript/jQuery
tool: texteditor, browser

download
https://getbootstrap.com/docs/4.0/getting-started/download/
bootstrap-4.0.0-beta-dist.zip
解凍して任意のフォルダに移動

Starter template
https://getbootstrap.com/docs/4.0/getting-started/introduction/
上記と同じにhtmlとして保存

ページを日本語化

titleを追記
# viewport はモバイル対応の為のもの

bootstrapstudy.html // --------------------
<'!DOCTYPE html>
<'html lang="ja">
<'head>
<'!-- Required meta tags -->
<'meta charset="utf-8">
<'meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

  <'!-- Title -->
  <'title>Bootstrap Study<'/title>
  
<'!-- Bootstrap CSS -->
<'link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
<'/head>
<'body>
<'h1>Hello, world!<'/h1>

  <'div id="header" class="container" style="background:salmon;">header<'/div>
  
  <'div class="container" style="padding:20px 0">
    <'div class="row">
      <'div class="col-sm-3 hidden-xs" style="background:skyblue;">leftside<'/div>
      <'div class="col-sm-6 col-xs-8">
        main
        <'table class="table table-bordered table-hover table-condensed"><'!-- table-striped -->
          <'thead>
            <'tr><'th>ID<'/th><'th>Score<'/th><'/tr>
          <'/thead>
          <'tbody>
            <'tr><'td>hoge<'/td><'td>100<'/td><'/tr>
            <'tr><'td>piyo<'/td><'td>200<'/td><'/tr>
            <'tr class="warning"><'td>higo<'/td><'td>300<'/td><'/tr>
          <'/tbody>
        <'/table>
        
        <'form>
          <'div class="form-group has-error">
            <'label class="control-label" for="email">Email<'/label>
            <'input type="text" id="email" class="form-control" placeholder="email">
            <'span class="help-block">Error!<'/span>
          <'/div>
          <'div class="form-group">
            <'input type="submit" value="submit" class="btn btn-primary">
          <'/div>
        <'/form>
        
        <'form class="form-inline">
          <'div class="form-group">
            <'label class="sr-only control-label" for="name">name<'/label>
            <'input type="text" id="name" class="form-control" placeholder="name">
          <'/div>
          <'div class="form-group">
            <'input type="submit" value="submit" class="btn btn-primary">
          <'/div>
        <'/form>

        <'form class="form-horizontal" style="margin-bottom:15px;">
          <'div class="form-group">
            <'label class="control-label col-sm-2" for="homephone">homephone<'/label>
            <'div class="cal-sm-4">
              <'input type="text" id="homephone" class="form-control" placeholder="name">
            <'/div>
          <'/div>
          <'div class="form-group">
            <'label class="control-label col-sm-2" for="cellphone">cellphone<'/label>
            <'div class="cal-sm-4">
              <'input type="text" id="cellphone" class="form-control" placeholder="name">
            <'/div>
          <'/div>
          <'div class="form-group">
            <'div class="col-sm-offset-2 col-sm-4">
              <'input type="submit" value="submit" class="btn btn-primary">
            <'/div>
          <'/div>
        <'/form>
        
        <'div class="container" style="padding:20px 0">
          <'p><'i class="glyphicon clyphicon-book"><'/i> Book<'/p>
          <'button class="btn btn-primary"><'i class="glyphicon clyphicon-book"><'/i> book btn<'/button>

          <'div class="btn-group">
            <'button class="btn btn-primary">btn<'/button>
            <'button class="btn btn-success">btn<'/button>
            <'button class="btn btn-info">btn<'/button>
          <'/div>
        <'/div>
        
        <'div class="container" style="padding:20px 0">
          <'div class="btn-group">
            <'button class="btn btn-primary dropdown-toggle" data-toggle="dropdown">
              btn <'span calss="caret"><'/span>
            <'/button>
            <'ul class="dropdown-menu">
              <'li><'a href="">aaa<'/a><'/li>
              <'li><'a href="">bbb<'/a><'/li>
              <'li class="divider"><'/li>
              <'li><'a href="">ccc<'/a><'/li>
            <'/ul>
          <'/div>
        <'/div>
        
        <'div class="container" style="padding:20px 0">
          <'div class="btn-group">
            <'button class="btn btn-primary">btn<'/button>
            <'button class="btn btn-primary dropdown-toggle" data-toggle="dropdown">
              <'span calss="caret"><'/span>
            <'/button>
            <'ul class="dropdown-menu">
              <'li><'a href="">ddd<'/a><'/li>
              <'li><'a href="">eee<'/a><'/li>
              <'li class="divider"><'/li>
              <'li><'a href="">fff<'/a><'/li>
            <'/ul>
          <'/div>
        <'/div>
        
        <'div class="container" style="padding:20px 0">
          <'ul class="breadcrumb">
            <'li><'a href="">Home<'/a><'/li>
            <'li><'a href="">User<'/a><'/li>
            <'li class="active">Piyo<'/li>
          <'/ul>
          
          <'ul class="pagination">
            <'li><'a href="">«<'/a><'/li>
            <'li class="diabled"><'a href="">0<'/a><'/li>
            <'li><'a href="">1<'/a><'/li>
            <'li class="active"><'a href="">2<'/a><'/li>
            <'li><'a href="">3<'/a><'/li>
            <'li><'a href="">0<'/a><'/li>
            <'li><'a href="">»<'/a><'/li>
          <'/ul>
          
          <'ul class="pager">
            <'li class="previous"><'a href="">前へ<'/a><'/li>
            <'li class="next"><'a href="">次へ<'/a><'/li>
          <'/ul>

          
        <'/div>

        <'div class="container" style="padding:20px 0">
        
        <'/div>



        
      <'/div>
      <'div class="col-sm-3 col-xs-4" style="background:lightblue;">rightside<'/div>
    <'/div>
  <'/div>
    
  <'div id="footer" class="container" style="background:plum;">footer<'/div>
  
<'!-- Optional JavaScript -->
<'!-- jQuery first, then Popper.js, then Bootstrap JS -->
<'script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"><'/script>
<'script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js" integrity="sha384-b/U6ypiBEHpOf/4+1nzFpr53nxSS+GLCkfwBdFNTxtclqqenISfwAzpKaMNFNmj4" crossorigin="anonymous"><'/script>
<'script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/js/bootstrap.min.js" integrity="sha384-h0AbiXch4ZDo7tp9hKZ4TsHbi047NrKGLO3SEJAg45jXxnGIfYzk4Si90RDIqNm1" crossorigin="anonymous"><'/script>
<'/body>
<'/html>
-------------------- // bootstrapstudy.html

tag : Bootstrap

2017-09-08 12:57 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] 今更ながらのWebフロント技術の勉強 - jQuery

今更ながらのWebフロント技術の勉強
で、手始めにjQuery

ref.
ドットインストール, jQuery入門 (全20回)
http://dotinstall.com/lessons/basic_jquery_v2
WEB色見本 原色大辞典
https://www.colordic.org/
いま Web サイトを作るときにおさえておきたい10のこと(2015年版)
https://blogs.msdn.microsoft.com/osamum/2015/02/06/web-10201529/
【使い方まで徹底解説】おすすめJavascriptライブラリ厳選10選!
http://www.sejuku.net/blog/4559#Bootstrap

jquerystudy.html // --------------------
<'!DOCTYPE html>
<'html lang="ja">
<'head>
  <'meta charset="utf-8">
  <'title>study<'/title>
  <'style>
    .myStyle {
      border:5px solid green;
      font-size:20px;
    }
  <'/style>
<'/head>
<'body>
  <'p>jQuery(ジェイクエリー)は、ウェブブラウザ用のJavaScriptコードをより容易に記述できるようにするために設計された軽量なJavaScriptライブラリである。<'/p>
  <'ul id="main">
    <'li>0<'/li>
    <'li class="item">1<'/li>
    <'li class="item">2<'/li>
    <'li>3
      <'ul id="sub">
        <'li>3-1<'/li>
        <'li class="item">3-2<'/li>
        <'li class="item">3-3<'/li>
        <'li>3-4<'/li>        
      <'/ul>
    <'/li>
  <'/ul>
  
  <'a href="http://google.com" data-sitename="site name is google">google<'/a>
  <'a href="http://yahoo.com">yahoo<'/a>
  <'a href="http://msn.com">msn<'/a>
  
  <'input type="text" value="hello">

  <'div id="box" style="width:100px; height:100px; background: orange;">
  <'/div>
  
  <'div id="box2" style="width:100px; height:100px; background: darkcyan;">
  <'/div>
  
  <'div id="box3" style="width:100px; height:100px; background: darkred;">
  <'/div>
  
  <'input type="text" id="name">
  <'select id="members" name="membersselection">
    <'option>hoge<'/option>
    <'option>piyo<'/option>
    <'option>foo<'/option>
    <'option>boo<'/option>
  <'/select>
  
  <'button>Add!<'/button>
  
  
  <'script
   src="https://code.jquery.com/jquery-3.2.1.js"
   integrity="sha256-DZAnKJ/6XZ9si04Hgrsxu/8s717jcIzLy3oi35EouyE="
   crossorigin="anonymous"><'/script>
  <'script>
    // $(document).ready(function() {
    $(function() {
      // セレクタ.メソッド
      // セレクタ: 処理対象となるDOM要素を指定する記法
      // メソッド: 処理
      $('p').css('color', 'red');
      // メソッドチェーン
      // $('p').css('color', 'red').hide('slow');
      // --------------------
      // セレクタの指定方法
      // HTML要素 - e.g. p h1 ul
      // CSS>id - e.g. #main
      // CSS>class - e.g. .item
      $("#sub").css('color', 'green');
      $(".item").css('color', 'blue');
      // > (不等号) = 直下の要素(子要素にのみ反映させる場合)
      $("#main > .item").css('color', 'orange');
      // (空白) = それ以下の要素(孫要素も反映させる場合)
      $("#main .item").css('color', 'brown');
      // , (カンマ) = 複数の要素
      $("p, .item").css('color', 'purple');
      // + (プラス) = 隣接する要素 - e.g. item要素の横にあるitem要素
      $(".item + .item").css('color', 'skyblue');
      // --------------------
      // フィルタ - :フィルタ名
      // :eq(), :gt() = greater than, :lt() = less than, :even = 偶数, :odd = 奇数, :contains(), :first, :last
      // :eq() - e.g. sub配下のliの2番目の要素(要素は0始まり)
      $("#sub > li:eq(2)").css('color', 'yellowgreen');
      // :gt() - e.g. 要素が2より大きい (3番目以降の項目)
      $("#sub > li:gt(2)").css('color', 'indigo');
      // :odd - e.g. 奇数番目の要素
      $("#sub > li:odd").css('color', 'violet');
      // :contains() - e.g. 値に'4'を含む項目
      $("#sub > li:contains('4')").css('color', 'deepskyblue');
      // --------------------
      // メソッドでdom要素指定
      // parent(), children(), siblings()
      $("#sub").parent().css('color', 'chocolate');//★TBC
      // next(), prev()
      $("#sub > li:eq(2)").next().css('color', 'orchid');
      // --------------------
      // 属性セレクタ
      // = 等しい、 != 等しくない、 *= 含む、 ^= で始まる、 $= で終わる
      $('a[href="http://google.com"]').css('background', 'silver');
      $('a[href!="http://google.com"]').css('background', 'gray');
      $('a[href*="msn"]').css('background', 'royalblue');
      // --------------------
      // css method
      // 値の取得 - e.g. 現在設定されている色を取得し、コンソールに表示させる
      console.log($('p').css('color'));
      // addClass/removeClass
      $('p').addClass('myStyle');
      // --------------------
      // attr
      console.log($('a').attr('href'));
      $('a').attr('href', 'http://google.co.jp');
      console.log($('a').attr('href'));
      // data (カスタム属性)
      console.log($('a').data('sitename'));
      // text, html, val, remove, empty
      $('p').text('just changed');
      $('p').html('<'a href="">click me!<'/a>');
      console.log('input.val is ' + $('input').val());
      $('input').val('hello, again!')
      $('p').empty();
      $('p').remove();
      // --------------------
      // 要素追加
      // before, after, insertBefore, insertAfter
      var li = $('<'li>').text('just added');
      $('ul > li:eq(1)').before(li)
      var li2 = $('<'li>').text('just added part2');
      li2.insertBefore($('ul > li:eq(2)'));
      // prepend, append. prepentTo, appendTo - 子要素の先頭/末尾に追加する
      // e.g. ulの子要素の先頭に追加する
      var li3 = $('<'li>').text('3rd just added');
      $('ul').prepend(li3);
      var li4 = $('<'li>').text('4th just added');
      li4.appendTo($('ul'));
      // --------------------
      // エフェクト
      // hide, show, fadeOut, fadeIn
      // toggle - 今消えていれば表示、表示されていれば消す
      // 8msecでhideする
      $('#box').hide(800);
      $('#box').fadeIn(800);
      $('#box').toggle('slow');
      // callback関数
      $('#box').show(800, function(){
        alert("done!")
      });
      // --------------------
      // event - click, mouseover, mouseout, mousemove
      $('#box2').click(function(){
        alert("hello!")
      });
      $('#box3')
        .mouseover(function() {//★TBC
          $(this).css('backgroud', 'darkgreen');
        })//セミコロンの有無に注意
        .mouseout(function() {//★TBC
          $(this).css('backgroud', 'olive');
        })//セミコロンの有無に注意
        .mousemove(function(e) {//event object
          $(this).text(e.pageX);
        });//セミコロンの有無に注意
      // --------------------
      // focus <'-> blur, change
      $('#name')
        .focus(function() {//★TBC//シャープを忘れずに
          $(this).css('backgroud', 'salmon');
        })
        .blur(function() {//★TBC
          $(this).css('backgroud', 'white');
        });
      $('#membersselection').change(function(){//★TBC
        alert('changed!');
      });
      // --------------------
      // ボタンを押す度にボタンの上に p を入れる
      $('button').click(function() {
        var p = $('<'p>').text('vanish!').addClass('vanish!');
        $(this).before(p);
      });
      /* vanishを消したい時、以下のやり方ではNG。
      pageがロードされた時にfunctionも読まれるが、その時点はvanishは存在しないから
      $('.vanish').click(function() {
        $(this).remove();
      });
      --> そこで ON を使う
      */
      $('body').on('click', '.vanish', function() {//★TBC
        $(this).remove();
      });
      // --------------------
      // Ajax = Asynchronous JavaScript + XML
      // サーバーと非同期通信 + ページの一部を書き換え
    });
  <'/script>
<'/body>
<'/html>
-------------------- // jquerystudy.html

tag : jQuery HTML CSS

2017-09-08 12:55 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] Newly faced products in September, 2017

Liferay
https://www.liferay.com

Apache Directory Studio
http://directory.apache.org/studio/

Apache Jmeter
CloudBerry Explorer

Cloud Foundry Command Line Interface (cf CLI)
https://docs.cloudfoundry.org/cf-cli/

Hinemos Client
http://www.hinemos.info/hinemos/getproduct

Amazon S3
https://aws.amazon.com/jp/s3/

S3 Browser
http://s3browser.com/

PuTTY: a free SSH and Telnet client
http://www.chiark.greenend.org.uk/~sgtatham/putty/

tag : PuTTY SSH Telnet S3 Amazon Hinemos Apache Cloud Jmeter Liferay

2017-09-08 12:52 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] ちょちょっとちょっとしたアンケートを作りたい

やっぱりgoogle formが簡単
でも、作成者はgoogleアカウントが必須

それが叶わぬ時は、以下が参考になるかも
外部サービス利用する場合はいずれにしても要アカウントだけど爆

ブログパーツ Webアンケート・ミニ投票システム
http://phpjavascriptroom.com/?t=topic&p=webpolls
アンケートフォームのサンプル
http://www.ark-web.jp/movabletype/demo/aform_pcmobile/enquete/index.html

といえど、Clientは知識を深めるに越したこと無し

Web制作の現場で使えるjQuery UIデザイン入門 ― 第10回
jQueryAjaxを利用する基本チュートリアル
http://ascii.jp/elem/000/000/458/458236/

新人プログラマですがjQueryのajaxがわからなすぎて勉強したまとめ
http://qiita.com/okumurakengo/items/53020dd97382d49621ce

tag : google form LimeSurvey jQuery Ajax

2017-09-04 00:45 : 開発 : コメント : 0 : トラックバック : 0 :

[開発][DB] この頃はやりのNoSQLなApache Cassandra

tag:
DB NoSQL Apache Cassandra データ・モデル カラム カラム・ファミリー キー・スペース

アスペを旦那に持つ妻が陥りやすいといわれるカサンドラ症候群
ではなくてDBの方。いろいろ概念から違うようで、とりあえずメモ。


ref.
IBM, developerWorks
Apache Cassandra データベースについての検討 - この NoSQL データベースの利点と欠点は何か?
Srinath Perera, 2012年 8月 02日
https://www.ibm.com/developerworks/jp/opensource/library/os-apache-cassandra/index.html

Qiita
Cassandra のデータ構造
mtakahashi-ivi, 2014年10月02日
http://qiita.com/mtakahashi-ivi/items/f9fab96675d1963be9a0

tag : DB NoSQL Apache Cassandra データ・モデル カラム カラム・ファミリー キー・スペース

2017-08-29 11:51 : 開発 : コメント : 0 : トラックバック : 0 :

[開発][JMS] Transaction界隈の確認に参照するシーケンスなメモ

spring-jms-4.3.5.RESEASE.jar

//Thread#run
//ThreadPoolExecutor$Worker#run
//StandardCOntext#startInternal
//StandardContext#listenerStart
//ContextLoaderListener#contextInitialized
//ContextLoaderListener#initWebApplicationContext
//ContextLoaderListener#confiureAndRefreshWebApplicationContext
//XmlWebApplicationContext#refresh
//DefaultLifecycleProcessor#onRefresh

//JmsListenerEndpointRegistry#start - 206
//JmsListenerEndpointRegistry#startIfNecessary - L.243
//DefaultMessageListenerContainer#start - L.598
//AbstractJmsListeningContainer#doStart - L.285
-- DefaultMessageListenerContainer#sharedConnectionEnabled - L.711
-- AbstractJmsListeningContainer#establishSharedConnection - L.381
-- -- AbstractJmsListeningContainer#createSharedConnection - L.413
-- -- -- JmsAccessor#createConnection - L.180
-- -- -- AbstractJmsListeningContainer#prepareSharedConnection - L.434
-- //DefaultMessageListenerContainer#startSharedConnection - L.822
-- -- AbstractJmsListeningContainer#startSharedConnection - L.448

loop: --------------------------------------------------------------------------

//Thread#run
//AsyncMessageListenerInvoker#run - L.1047
-- //AsyncMessageListenerInvoker#executeOngoingLoop - L.1158
-- -- //AsyncMessageListenerInvoker#invokeListener - L.1166
-- -- -- AsyncMessageListenerInvoker#initResourceIfNecessary - L.1184
-- -- -- -- AbstractJmsListeningContainer#getSharedConnection - L.491

-- -- -- //AbstractPollingMessageListenerContainer#receiveAndExecute - L.232
-- -- -- -- //ChainedTransactionManager#getTransaction - L.101
-- -- -- -- -- //MultiTransactionStatus#registerTransactionManager - L.68
-- -- -- -- -- //JmsTransactionManager#getTransaction - L.373
-- -- -- -- -- -- JmsTransactionManager#doBegin - L.186 ★BREAKPOINT

-- -- -- //AbstractPollingMessageListenerContainer#receiveAndExecute - L.235
-- -- -- -- AbstractPollingMessageListenerContainer#doReceiveAndExecute - L.302 - ☆AsyncRcv ★BREAKPOINT
-- -- -- -- -- //AbstractPollingMessageListenerContainer#receiveMessage - L.416
-- -- -- -- -- //AbstractMessageListenerContainer#doExecuteListener - L.651
-- -- -- -- -- -- //AbstractMessageListenerContainer#invokeListener - L.681
-- -- -- -- -- -- -- //MessagingMessageListenerAdapter#onMessage - L.69
-- -- -- -- -- -- -- -- //MessagingMessageListenerAdapter#invokeHandler
-- -- -- -- -- -- -- -- -- //MyJmsListener - ☆transaction boundary
-- -- -- -- -- -- -- -- -- -- //MyServiceImpl - ☆transaction boundary
-- -- -- -- -- -- -- -- -- -- -- JmsTemplate#doSend - L.591 - ☆SyncSend ★BREAKPOINT
-- -- -- -- -- -- -- -- AbstractAdaptableMessageListener#sendResponse - L.399 - ☆Reply ★BREAKPOINT

-- -- -- -- -- //AbstractMessageListenerContainer#doExecuteListener - L.665
-- -- -- -- -- -- AbstractMessageListenerContainer#commitIfNecessary - L.757 ★BREAKPOINT
-- -- -- -- -- -- -- //JmsUtils#commitIfNecessary - L.217
-- -- -- -- -- //AbstractMessageListenerContainer#doExecuteListener - L.658
-- -- -- -- -- -- //AbstractMessageListenerContainer#rollbackOnExceptionIfNecessary - L.800
-- -- -- -- -- -- -- JmsUtils#rollbackIfNecessary

-- -- -- //AbstractPollingMessageListenerContainer#receiveAndExecute - L.249
-- -- -- -- //AbstractPlatformTransactionManager#commit
-- -- -- -- -- JmsTransactionManager#doCommit - L.234 ★BREAKPOINT

-------------------------------------------------------------------------- :loop

tag : Spring JMS transaction JmsUtils JmsTemplate ChainedTransactionManager JmsTransactionManager

2017-07-13 21:39 : 開発 : コメント : 0 : トラックバック : 0 :

[開発][JMS] ActiveMQ Broker な話

apache-activemq-5.14.1

■ Running an ActiveMQ Broker
組込Brokerを使いたい場合は「How do I embed a Broker inside a Connection」参照

先ず、ActiveMQ Brokerの実行
cd C:\apache-activemq-5.14.1\bin
activemq console

次に、brokerの挙動を指定。方法は3つ。推奨されるのは Broker XBean URI。

- Broker Configuration URI での指定
  e.g.
  activemq console broker:(tcp://localhost:61616,network:static:tcp://remotehost:61616)?persistent=false&useJmx=true

- Broker XBean URI での指定
  e.g.
  activemq console xbean:foo.xml

- Broker Properties URI での指定
  e.g.
  activemq console properties:foo.properties

 ref.
 http://activemq.apache.org/broker-xbean-uri.html

Web ConsoleでActiveMQの監視
 http://localhost:8161/admin
 admin/admin

以下の場合は、本家サイト参照
- brokerをServletエンジンで実行させる場合
- brokerをJ2EEアプリサーバで実行させる場合
- brokerをソースコードで実行させる場合
- brockerをmavenで実行させる場合

brokerのfailover時に、brokerが自動でdetectして再接続するようにする為には、
 URIを以下のように変える
 failover:tcp://host:port
 ref.
 http://activemq.apache.org/configuring-version-5-transports.html

ref.
Running an ActiveMQ Broker
http://activemq.apache.org/version-5-run-broker.html

■ Broker XBean URI での指定方法
対象のフォルダの在り処
C:\apache-activemq-5.14.1\conf\activemq.xml

ActiveMQ ver5.3 以降のものには KahaDBが推奨される

AMQ Message Store とは
ActiveMQ ver5+ にあるデフォルトのストレージ。
組み込み式トランザクションが張られたメッセージの処理に有用
メッセージのコマンドは、transaction journalに書き込まれる
deta logとして残す事で、メッセージを永続化している。=default kaha

□ 設定
デフォルトでは、AMQ Store が使用されるが、永続化などamqPersistenceAdapterで設定変更可能
e.g.
<'broker brokerName="broker" persistent="true" useShutdownHook="false">
  <'persistenceAdapter>
    <'amqPersistenceAdapter directory="${activemq.base}/activemq-data" maxFileLength="32mb"/>
  <'/persistenceAdapter>
  <'transportConnectors>
    <'transportConnector uri="tcp://localhost:61616"/>
  <'/transportConnectors>
<'/broker>

tag : ActiveMQ Broker JMS activemq AMQ

2017-07-13 21:32 : 開発 : コメント : 0 : トラックバック : 0 :

[開発][JMS] AMQで電文永続化

AMQでのJMSメッセージを永続化したい

ActiveMQは予期せぬエラーでMessageBrokerが終了してしまった場合、未送信のメッセージを保持する機能を持っています。」
これがしたい。

使用する JMS MOM(Message Oriented Middleware)は Active MQ。
永続化先はデータベース
アプリ側は Spring、DBは PostgreSQL を使いたい。

とか色々と思考したけど、
管理コンソールの「Send To」で「Persistent Delivery」にチェックすれ良いだけだった!爆
http://127.0.0.1:8161/admin/send.jsp?JMSDestination=TmpTestQueue&JMSDestinationType=queue

ref.
ActiveMQでメッセージキューを実装する, 2013.07.24
http://www.geek.sc/archives/1030
AMQ x MySQL

Efficient Lightweight JMS with Spring and ActiveMQ, 2009/10/16
https://codedependents.com/2009/10/16/efficient-lightweight-jms-with-spring-and-activemq/
Spring x AMQ (incl. ExceptionListener)

JMS PERSISTENCE
http://forum.spring.io/forum/spring-projects/integration/jms/10577-jms-persistence
how to get msgs redelivered as soon as restarting a server after a failover, using AMQ x JDBC x embeddedBroker

Spring Boot Example of Spring Integration and ActiveMQ
https://dzone.com/articles/spring-boot-example-of-spring-integration-and-acti

etc.
http://activemq.apache.org/spring-support.html
http://activemq.apache.org/version-5-run-broker.html
http://activemq.apache.org/how-do-i-embed-a-broker-inside-a-connection.html
http://activemq.apache.org/how-can-i-monitor-activemq.html

--------------------------------------------------

[脱線] H2とは
H2 Database Engineは、Apache Derby、HSQLDB、Berkeley DB と並ぶ組み込みデータベース
中でもH2はパフォーマンスが高いと言われる
http://www.h2database.com/html/main.html
特徴
・全てJava。でもネイティブ版もある。
・組込モードとサーバモードとある
・クラスタリングにも対応

[脱線] PostgreSQL の操作
手段は主に3つ

□ WIndowsのコマンドプロンプトでPostgresSQL操作
スタートメニュー>コマンドプロンプト
"C:/Program Files/PostgreSQL/9.4/bin/psql" postgres postgres
select * from pg_tables where not tablename like 'pg%' order by tablename;

□ PostgresSQL付属のコマンドラインアプリで操作
スタートメニュー>SQL Shell(psql)を起動

□ pgAdminでPostgresSQL操作
http://www.pgadmin.org/ からmsiファイルをDLして来てインストール
スタートメニュー>pdAdminIIIを実行
「サーバに接続の追加」>適当に名称入れて、接続パスワード(postgresインストール時に設定したヤツ)だけ入れて後はデフォルトのまま「OK」
繋がらない場合に確認>C:\Program Files\PostgreSQL\9.4\data\postgresql.conf
PostgreSQLで外部からのTCP接続を許可していない場合があるので。
要チェックなパラメータ
listen_addresses TCP接続を許可するIPアドレスを指定。デフォルトは「localhost」で、自分自身のサーバーからしか接続を許可しない。
port 待ち受けるポート番号を指定。デフォルトは5432。
log_destination PostgreSQLが出力するログ出力先を指定。
pg_hda.confファイルの編集

tag : AMQ JMS ActiveMQ MessageBroker MOM Spring PostgreSQL PERSISTENCE H2

2017-07-07 20:06 : 開発 : コメント : 0 : トラックバック : 0 :

Sphinx / reStructuredText の参照情報

このところは rst が主流のようで、、

Sphinx / reStructuredText の参照情報

reStructuredText構文
http://www.ne.jp/asahi/hishidama/home/tech/sphinx/rest.html
はやわかり reStructuredText
http://www.planewave.org/translations/rst/quickref.html/restructuredtext.html
Sphinxでの文章の書き方(reStructuredText)
http://planset-study-sphinx.readthedocs.io/ja/latest/04.html

tag : Sphinx reStructuredText rst

2017-07-07 20:02 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] 文字化けな話

H2から取って来たデータが文字化けする。

とりあえず、
STS>Run>Run Configurations... >Common>Encoding>Other>UTF-8
にしとけ。

Something Detail:
spring-jdbc-4.2.7.RELEASE.jar>META-INF>spring.handlers
org.springframework.jdbc.config.JdbcNamespaceHandler
InitializeDatabaseBeanDefinitionParser ext. AbstractBeanDefinitionParser#parseInternal(element, parserContext)
DatabasePopulatorConfigUtils.setDatabasePopulator(element, builder)
getAttribute("encoding")
EncodedResource#encoding

tag : Spring spring jdbc H2 STS Encoding InitializeDatabaseBeanDefinitionParser JdbcNamespaceHandler

2017-07-07 19:57 : 開発 : コメント : 0 : トラックバック : 0 :

[開発][谷本心] Java本格入門

Chap.1 Javaの基本を知ろう

Java SE – Standard Edition
Java EE – Enterprise Edition
Java ME – Micro Edition
JRE – Java Runtime Environment
JDK – Java Development Kit


Chap.2 基本的な書き方を身につける

Java VM – HotSpot, JRockit, IBM JVM, HP-UX JVM, Zing, OpenJDK

Javaの基本的な記法
- 文とブロック
- コメント
- 変数、型、リテラル ※ リテラル = 変数に代入する値を具体的に表現したもの
- 演算子:単項演算子, 二項演算子, 三項演算子
- 数術演算子:+, -, *, /, %, - (単項演算子), ++ (単項演算子), -- (単項演算子)
- 関係演算子:==, !=, >, >=, <, <=, instanceof
- 条件演算子:<条件> ? 式1 : 式2
- 論理演算子:&&, ||, ! (単項演算子)
- ビット演算子:&, |, ^ (ビット演算XORを行う), <<, >>, >>>, ~ (単項演算子, bitを反転する)
- 代入演算子:=, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=, >>>=
- 文字列結合に利用する演算子:+, +=
- 制御構文:if, switch, for / for-each, while / do…while
- クラスとメソッド
- 修飾子:アクセス修飾子, abstract修飾子, static修飾子, final修飾子, transient修飾子, volatile修飾子, synchronized修飾子, native修飾子, strictfp修飾子
# static – classがinstance化されていなくてもaccessできるmemberに付ける
# final – 大文字のスネークケースで定義する
# transient – objectのserialize時にserialize対象から除外される
# volatile – multithreadからaccessされるfieldがthread毎にcacheされないようにする
# synchronized – 同時に1threadだけ実行できることを指定する
# native – C/C++などJava以外のnative codeを呼び出すことを指定する
# strictfp – 浮動小数点をIEEE 754企画で厳密に処理することを指定する
- メソッドのオーバーライド
- インスタンス
- thisを用いた記述の注意点
- コンストラクタ

- Javadoc
- アノテーション - @Override, @Deprecated. @SuppressWarnings
- クラスと変数はキャメルケースで、定数はスネークケースで
- 変数名の後ろに_は付けない
- 変数は名詞、メソッドは動詞で命名すべし
- 「不吉な匂い」がする名前は要注意

Chap. 3 型を極める

Javaは静的型付け言語
# 言語次第で型が決まるtiming異なる―静的片付け言語 と 動的型付け言語
# JavaScriptやRubyは動的片付け言語
Javaの型は2種類 ― プリミティブ型 と 参照型
プリミティブ型:byte, short, int, long, char, float, double, Boolean
- リテラルによるプリミティブ型変数の宣言 ― ★なだ謎い
- ライドニングとナローイング ― e.g. int intNum = shourtNum; // ワイドニングによる自動変換

参照型
- 参照(ポインタ)
- 文字列リテラル
- nullリテラル

ラッパークラス
- プリミティブ型(基本型)はobjectでなく単なるvalue = methodを持たない
- プリミティブ型に対する操作はラッパー(参照型)に入れて扱う - e.g. primitive: byte = wrapper: java.lang.Byte
- wrapperクラスによくあるmethodたち:#valueOf, #pareseXxx, #toString
- primitiveはnullを持てない = null checkが不要

オートボクシングとアンボクシング ― 「==」演算子とかでは注意が必要
primitive  wrapper class への自動変換 = オートボクシング Autoboxing
wrapper class  primitive への自動変換 = アンボクシング Unboxing
autoboxing/unboxingは利用せずに明示的に変換するのが無難

クラスを定義する
パッケージ
# FQCN = fully qualified class name
アクセス修飾子
- 対クラス:public, default
- 対メソッド:public, protected, default, private
その他の修飾子:static, final

継承
抽象クラス
インタフェース
匿名クラス - ref. ラムダ式
Nested class - ref. Effecitve Java 第2版

Instanceof演算子
オブジェクトの等価性
- hashCodeメソッド - 自身のobjectの内容を新た巣数値(ハッシュ値)=同じ値を持つオブジェクトは同じハッシュ値となる
- ハッシュ値比較はequals比較より速い。※ hashCodeとequalsを両方が等価条件
- Objects.hash で hashCode 作れる (Java 7 +)
- デフォのtoString は、基底クラスのObject#toString のhashCode になる
- メソッドチェイン形式での文字連結 = StringBuilder#append

型にまつわる問題の予防
列挙型 enum
- public static finalは型安全でない=不正に動作する可能性あり
- 大文字で定義するのはpublic static finalと同じ
- switch 文にも利用可能
- enumのconstructor は privateとすること

ジェネリクス (総称型) – java 5 +
List list = new ArrayList<>();
# Java 7+であればダイヤモンドオペレータで略式定義が可能
Stack, push, pop, remove – null check 要。
仮型パラメータE でジェネリックス定義例
List list;
# list.forEach(stack::push)なことも可能
public class HogeClass
# extends 以外にsuper, 不定を表す?も使用可能- cf. Effective Java 第2版


Chap. 4 配列とコレクションを極める
System.arraycopy(oldArray, 0, newArray, 0, oldArray.length);
Int[] newArray2 = Arrays.copyOf(oldArray, oldArray.length + 2);
上記両者の性能は互角
Int[] array = {1, 1, 2, 3, 5, 8, 13};
System.out.println(array);  [I@1bb60c3 = [ (配列) + I (int型) + @1bb60c3 (ハッシュ値)
System.out,println(Arrays.toString(array));  [1, 1, 2, 3, 5, 8, 13]
Arrays.sort(array);
プリミティブ型の場合  値の昇順でsort
オブジェクト型の場合  Comparable インタフェースの compareTo でsort ( = ComparableをimplしてないとClassCastException)

Sort by Comparable  デフォルトソートとして利用
Sort by Comparator  業務的に必要な順序にソート

Arrays.binarySearch (2分探索)

void hogeMethod(String… args)

Collection > List, Set, Map

List : ArrayList, LinkedList(順序保持リスト), CopyOnWriteArrayList(ThreadSafeなArrayList)
add, addAll, set, remove, removeAll, retainAll (一致しない要素の削除), clear
get, size, isEmpty, subList, toArray
contains, containsAll, indexOf, lastIndexOf
iterator, listIterator
Collections.sort

for (String element : list) { … }
*
for (Iterator iterator = list.iterator(); iterator.hasNext(); ) {
….String element = iteratory.next();
….System.out.println(element);
}
*
Iterator iterator = students.iterator();
while (literator.hasNext()) {
….Student student = iterator.next();
….if (student.getScore() < 70) {
……..iterator.remove();
….}
}

ArrayList: 追加○, 挿入○, 値取得◎, 検索×  for文を使う
LinkedList: 追加◎, 挿入◎, 値取得×, 検索×  要素の追加削除が多い
CopyOnWriteArrayList: 追加○, 挿入○, 値取得◎, 検索×  複数threadからの同時アクセスあり

Map
HashMap:
-内部のHashTableにデータ保持=参照が速い
-無限ループに注意
-ThreadSafeでない。→ synchronizedにするかThreadSafeのConcurrentHashMapを使う
LinkedHashMap
-HashMapのSubClass
-要素追加順を保持する
TreeMap
-二分探索木

HashMap: 追加◎, 取得◎, 列挙◎
LinkedHashMap: 追加◎, 取得◎, 列挙◎
ConcurrentHashMap: 追加○, 取得○, 列挙○
TreeMap: 追加△, 取得△, 列挙△

Set: 重複を持たない
HashSet
LinkedHashSet
TreeSet
# ThreadSafeなSetが欲しい時はCollections.newSetFromMap(new ConcurrentHashMap())で作れる

Queue#poll, peek
Deque

Chap. 5 ストリーム処理を使いこなす - ラムダ式とStream API -


pp.150

tag : 谷本心 Java本格入門

2017-06-27 23:15 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] Message Brocker って結局、何者?

tag.
JMS Message Brocker MOM Queue

■ ことのはじまり
JMSで送受信する電文(メッセージ)が環境障害時に消失しないよう、DBなりに永続化して置きたい
その為に、単純にMOMに繋げるのではなく、Brokerを仲介させる必要があるげ?

てか、broker を今ひとつ掴み切れて無い
WebSphere Message Broker とか rich な感じはぷんぷんするが必須なのか?何が嬉しいのだ?

■ JMS Message Broker の意義
JMS Messaging product に含まれる物:
-Brocker: A JMS broker provides connectivity, message storage, and message delivery functions to its clients. It also provides quality of service features, such as reliability, persistence, security, and availability.
- Messages
- Destinations
- Clients (Producer / Consumer)
- Connections: Connections are the technique used by clients to specify a protocol and credentials for a sustained client interaction with a broker.
- Sessions: Sessions are defined by a client on a conection established with a broker. Each session defines whether the messages will form transactions, and -- if not -- the acknowledgement mode for messages.

画像検索してもなんだかBrockerがJMSの一部というかQueueなりTopicなりの実体を保持する輩に見えるが
WebSphere MQ と WebSphere Message Brock と別にあるということは別物。ん?どゆこと?

「ActiveMQでは中継を行うサーバのことをMessageBrokerと呼んでいます。」 (TechScore)
「WebSphere Message Brokerはそんな時代にEAIにおける「ハブ」製品」 (IBM developerWorks)

そもそも共通定義が無い!?
「There is not really an official definition for what a JMS broker is, but there is conceptual difference between a message queue and broker.」 (stackoverflow)
ビンゴ!共通定義はないが、Queue と Message Brocker は別物。

┏━━━━━━━━━━━━━━━━━━━━
┃■ Queue は、
┃msg の header だけを見る。それを元に電文送信する。
┃msg の body は決して見ないし、msg の変換とか変な事も一切しない。
┃悪までも電文送信が任務。

┃■ Message Brocker は、
┃Queue と違ってプログラム実行環境を提供する。
┃なので、msg の body を解析したり、よしなに変換したりできる。
┃=ミドルなりアプリのversion upで生じたひずみを吸収することも可能。

┗━━━━━━━━━━━━━━━━━━━━

Message Brocker の一番の意義は、

The big value of message brokers is that they can do some really nice things for you for handling message concurrently, fail-over for processing logic, deploying of processing logic, monitoring and logging ... etc. Think of a message broker as a specialized application server for writing message processing code, possibly in a custom high level language. For example IBM message broker can be programmed in a ESQL an extension of SQL along with a diagrams and nodes that you connect with each other. Programs written for a message borker will be shorter than if you wrote all the code yourself using plain JMS.

Brokers can be centralized or distributed, so for example you can have a central broker in New York, an have clients in London and Hong kong connected to it. Or you could have the broker be distributed and have an instance running in London and Hong kong which do the message processing closer to the source / destination of the message, it will all depend on your management infrastructure and what other resources like databases the message broker needs to talk to.


ref.
エンタープライズ・メッセージング! JMS編 前編
http://www.acroquest.co.jp/webworkshop/JavaNetwork/NP_lecture05.html
CORBA等のRPC(Remote Procedure Call)という通信方式とJMSとの違い

JMS Basics, JMS components
https://access.redhat.com/documentation/en-US/Fuse_Message_Broker/5.4/html/Getting_Started/files/FuseMBStartedKeyJMS.html
MOMが包含する登場人物の紹介。分かり易い

JMS Development, Basic broker application components
https://access.redhat.com/documentation/en-US/Red_Hat_JBoss_Fuse/6.0/html/Product_Introduction/files/JMSdev.html
アプリ側の処理フロー。分かり易い

JMS Messaging Objects and Patterns, Sun Java System Message Queue 4.1 Technical Overview
https://docs.oracle.com/cd/E19717-01/819-7759/aeras/index.html
RedHatより深いが、その割には分かり易そう

JMSの基礎, 2006.09.20
http://www.techscore.com/tech/Java/JavaEE/JMS/1/
ActiveMQサーバ/MessageBrokerの起動

What is the responsibility of a JMS broker in the JMS Eco system?
https://stackoverflow.com/questions/14152648/what-is-the-responsibility-of-a-jms-broker-in-the-jms-eco-system
JMS Brokerとは何か。


tag : JMS Message Brocker MOM Queue WebSphere MQ

2017-06-07 13:58 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] Spring JMS の AbstractMessageListenerContainer っていう奴

tag:
JMS Spring AbstractMessageListenerContainer AbstractPollingMessageListenerContainer DefaultMessageListenerContainer SimpleMessageListenerContainer sessionAcknowledgeMode acknowledge sessionTransacted JtaTransactionManager JmsTransactionManager TransactionAwareConnectionFactoryProxy


Java 1.0a(アルファ版)がダウンロードできるようになったのが1994年
対し、JMSのfirst releaseが2001年
その差たった7年
Javaはともかく、JMSが未だに現役なのが凄い

両者とも取り巻く登場人物の変化は大きい
一番はやはりSpring?になるのか?
そのSpringも決してJMSを無視して折らず、Spring JMSがある
https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/html/jms.html


JMSのそもそも仕様で、
開発者部品の任意のタイミングでJMS Providerに接続して電文を受信する同期受信と
JMS Providerが電文を受信したタイミングで開発者部品が呼び出される非同期受信とあるが、
Springもまたその両方をサポートしている。
特に後者の非同期受信でスポットライトを浴びるのが以下のSpringのクラスたち
AbstractMessageListenerContainer - AMLC
├- AbstractPollingMessageListenerContainer - APMLC
│ └- DefaultMessageListenerContainer - DMLC
└- SimpleMessageListenerContainer - SMLC

こやつ等を使用した非同期電文受信からのDB更新を同一トランザクションで管理できるか
というテーマが繰り広げられる訳なのだが、

その前提ともなる大切な事がAMLC のJavadocにしれっと書いてるのでメモメモ
Class AbstractMessageListenerContainer
http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jms/listener/AbstractMessageListenerContainer.html
・ JMS の MessageListener を使うでも Spring SessionAwareMessageListener を使うでも良し
・ 通常はJMS Connectionを1つだけ保持し、全てのlistenerがそれを使いまわす。=超標準的なJMSのlistener sessionの管理方法
・ 外部リソースと同一トランザクションにするなどXAを使用する時は新規にConnectionを設ける。プロセスの登録はサブクラス依存
NOTE:
- デフォルトの message listener container は、如何なる例外が発生しようとも、log だけ吐いて JMS Provider へ回さない。
  =非同期受信がrollbackされ、一度受信した電文がQueueに返ることは無い ★留意されたし★
- と言えども、その発生例外をハンドリングしたい場合は、setErrorHandler で任意の例外ハンドラを設定すること
  ただし、その例外ハンドラは ExceptionListener が呼ばれた後に呼ばれることにご注意あれ ★留意されたし★

非同期受信した電文をQueueからdeleteしても良いかをJMS Providerに伝える仕組みがacknowledgeなるもの
acknowledgeすると電文がQueueから消える訳だが、コイツがまた曲者。


AMLC が提供する acknowledge オプションは以下の4つ:
- 1. sessionAcknowledgeMode = AUTO_ACKNOWLEDGE (default)
- 2. sessionAcknowledgeMode = DUPS_OK_ACKNOWLEDGE
- 3. sessionAcknowledgeMode = CLIENT_ACKNOWLEDGE
- 4. sessionTransacted = true

各オプションの詳細:

-- 1. sessionAcknowledgeMode = AUTO_ACKNOWLEDGE (default)
DMLC の場合 >>
  非同期受信した電文をacknowledgeしてから、listenerが呼ばれる。 ★留意されたし★
  電文のロールバックは起こりえず、同一電文が他のlistenerに食われることもない=同一電文の再配信なし ★留意されたし★
SMLC の場合 >>
  listenerが呼んでから、非同期受信した電文をacknowledgeする。 ★留意されたし★
  どんな例外が発生しようが電文のロールバックはしない=同一電文の再配信なし(DMLCと同じ) ★留意されたし★
  ※ ただし、JVM異常時はロールバックする可能性あり

-- 2. sessionAcknowledgeMode = DUPS_OK_ACKNOWLEDGE
lazy message acknowledgmentをするだけで、後はAUTO_ACKNOWLEDGEの時に同じ

-- 3. sessionAcknowledgeMode = CLIENT_ACKNOWLEDGE
呼び出されたlistenerの処理が成功した場合にのみacknowledgeする。
例外発生時は「best effort」で非同期受信をロールバックする=同一電文の再配信あり

-- 4. sessionTransacted = true
呼び出されたlistenerの処理が成功した場合にのみacknowledgeする。
例外発生時は「必ず」で非同期受信をロールバックする=同一電文の再配信あり

そんなこんなで同一電文の重複配信(duplicate message processing problem)の可能性は拭えない
対処法は2つ
・listenerに重複判定するロジックを入れる。cf. JMSRedelivered flag
・XAトランで全処理をラップする。
※ XAトランはオーバーヘッドがかかる点に留意されたい


☆ 推奨手法
sessionTransacted = ture にしとくがよろし。
  特に listener からlocalのDBを更新する場合。
  ただし、重複配信の対策はロジックでよしなにやる必要あり。
・ もしくは、JtaTransactionManager をtransactionManagerに設定してXAトランにする。

☆ 注意
XAトランかJTAの場合にのみ、JmsTransactionManagerを使用し、
それ以外の場合は、sessionTransacted を使用するのが良い (JtaTransactionManagerは使わずに)。


所変わって、APMLC
AbstractPollingMessageListenerContainer#setTransactionManager
http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jms/listener/AbstractPollingMessageListenerContainer.html#setTransactionManager-org.springframework.transaction.PlatformTransactionManager-
電文の受信とlistener処理をwrapするトランのマネージャを登録する。
デフォはnull
設定される場合は、基本 Spring の JtaTransactionManager かそのさぶクラス。JTA-aware ConnectionFactory とsetで使用するのが王道

NOTE:
JTA より local JMS transaction の使用を検討すべき。
local JMS transaction なら、単純にsessionTransactedをtrueにするだけで、非同期受信以降の SessionAwareMessageListenerで呼び出されるsessionを包括できる。
つまり、JmsTransactionManagerと同等のことをlocal JMS transactionで叶う。


で、そのJmsTransactionManagerとは何ぞや?
http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jms/connection/JmsTransactionManager.html
・ 任意のConnectionFactoryからConnectionとsessionを取得してthreadに割り振るのが仕事。
・ local strategyで、JTA でのJMS実行の代替手段
・ Prosは、如何なる環境で作動すること。Standaloneでもtest suiteでもmessage brokerとの連携だって可能。
・ Consは、JMSトランとDBトランを1トランで扱うなどのJTA/XAトランの制御はできない。それやるなら、SpringのJtaTransactionManagerをstrategyとすべき。


## なんかもやっとする
## AUTO_ACKNOWLEDGEやDUPS_OK_ACKNOWLEDGEは良いけど、
## sessionTransacted=trueで基本的に有無言わさず非同期受信をcommit(acknowledge)するかどうか記述が曖昧
## sessionTransactedにする場合は、JVM死亡時以外は非同期受信電文のrollback無しな表現がまた曖昧
## plus, 仮にJVM死亡時以外は非同期受信電文のrollback無しの場合、他のacknowledge optionとの違いは何??


で、ググってたら新キャラ登場
TransactionAwareConnectionFactoryProxy - TACFP
ref.
Dr. David Syer, Distributed transactions in Spring, with and without XA - Seven transaction-processing patterns for Spring applications, JAN 6, 2009 12:00 AM PT
http://www.javaworld.com/article/2077963/open-source-tools/distributed-transactions-in-spring--with-and-without-xa.html
な、長い..

tag : JMS Spring AbstractMessageListenerContainer AbstractPollingMessageListenerContainer DefaultMessageListenerContainer SimpleMessageListenerContainer sessionAcknowledgeMode acknowledge sessionTransacted JtaTransactionManager

2017-06-05 20:02 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] CSRF/XSSはいずれも脆弱性の1つで、もしくはそれを利用した攻撃のことを言う

cross-site request forgeries
クロスサイトリクエストフォージェリ
CSRF (シーサーフ)
リクエスト強要

Webアプリケーションの脆弱性の一つもしくはそれを利用した攻撃

別のサイトに用意したコンテンツ上の罠のリンクを踏ませること等をきっかけとして、
インターネットショッピングの最終決済や退会等Webアプリケーションの重要な処理を呼び出すようユーザを誘導する攻撃である。

ブラウザが正規の Webコンテンツにアクセスした際には毎回、
セッションを維持するために所定の Cookie、Basic認証データあるいは Digest認証データがブラウザから Webサーバ宛に送出されるという性質を、この攻撃は悪用する。

----------------------------------------

cross site scripting
クロスサイトスクリプティング
XSS

他人のWebサイトへ、悪意のあるスクリプトを埋め込むこと
Webアプリケーションの脆弱性もしくはそれを利用した攻撃
Webサイトへの代表的な攻撃手法

----------------------------------------

相違

同じ>
― どちらも「クロスサイト」という言葉が先頭につく
― なりすましのようなことが結果としてできる
― どちらも受動型攻撃である

違う>
XSSはブラウザ上でスクリプトが動き、CSRFはサーバー上でスクリプトが動く


ref.
リクエスト強要(CSRF)対策
https://www.ipa.go.jp/security/awareness/vendor/programmingv2/contents/301.html
クロスサイトスクリプティング(XSS)とCSRFの違い早分かり
http://d.hatena.ne.jp/ockeghem/20071203/p1

tag : XSS CSRF

2017-04-22 00:36 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] Authentication vs. Authorization vs. Verification

Authentication
認証
ユーザIDとパスワードとか本人確認をしてサービスにログインするときなどに使用

Authorization
認可
認証してサービスにログインするわけではなく、特定の期間や特定の条件のもとで情報へのアクセスを認可するときなどに使用
=ログイン処理を通さずにサービスやユーザ情報を取得したりする

Verification
検証
サービス提供側がその人が今ログイン使用としてるユーザと本当に同じ人物なのか確認


cf.
- OAuthは、authentication より authorization として使用されるべき、と。
- Googleは、2-Step Verification
- Githubは、2-factor Authentication


ref.
【プログラマ英語】それ認証って意味じゃないですよ(厳密には)
http://qiita.com/tienlen/items/9e1b58dd173472f071c0

tag : Authentication Authorization Verification

2017-04-21 22:00 : 開発 : コメント : 0 : トラックバック : 0 :

[ORM][MyBatis] 単純な文字列リストを入れ子に持つBeanへのResultMap定義

■ 事象
The content of element type "resultMap" must match "(constructor?,id*,result*,association*,collection*,discriminator?)". mybatis
要素タイプ"resultMap"のコンテンツは"(constructor?,id*,result*,association*,collection*,discriminator?)"と一致する必要があります。
org.apache.ibatis.builder.BuilderException
org.xml.sax.SAXParseException
 
■ 原因
resultMap の Schema 違反
 
■ 対応
以下のように result の定義を全部 collection の前にする
|    <'resultMap id="accountMap" type="myproject.Account">
|        <'id property="userId" column="user_id" />
|        <'result property="firstName" column="first_name" />
|        <'result property="lastName" column="last_name" />
|        <'result property="status" column="status" />
|        <'result property="lastUpdate" column="last_update" />
|               <'collection property="roles" ofType="java.lang.String" javaType="list">
|                   <'result column="role_column" />
|               <'/collection>
|    <'/resultMap>
 
Beanのfield定義順にしたいところだけど、以下のようにしてはダメ
|    <'resultMap id="accountMap" type="myproject.Account">
|        <'id property="userId" column="user_id" />
|        <'result property="firstName" column="first_name" />
|        <'result property="lastName" column="last_name" />
|               <'collection property="roles" ofType="java.lang.String" javaType="list">
|                   <'result column="role_column" />
|               <'/collection>
|        <'result property="status" column="status" />
|        <'result property="lastUpdate" column="last_update" />
|    <'/resultMap>
 
[参考] SQL 定義はこんな感じ
    <'select id="findOne" parameterType="String" resultMap="accountMap">
    <'![CDATA[
        SELECT
            a.user_id,
            a.first_name,
            a.last_name,
            r.role as role_column,
            a.status,
            a.last_update
        FROM
            ACCOUNT_TBL a, ROLE_TBL r
        WHERE
            a.user_id = #{userId}
            AND a.user_id = r.rltbl_user_id
    ]]>
    <'/select>
 
[参考] Beanはこんな感じ
public class Account implements Serializable {
 
              private static final long serialVersionUID = 1L;
 
              private String userId;//user_id
              private String firstName;//first_name
              private String lastName;//last_name
              private List<'String> roles;//role
              private String status;//status
              private Date lastUpdate;
 
[参考] こんな書き方もいろいろ ― 未検証w
 
    <'select id="findOne" parameterType="String" resultMap="accountMap">
    <'![CDATA[
        SELECT
            a.user_id,
            a.first_name,
            a.last_name,
            (
                SELECT r.role as role_column
                FROM role_tbl r
                WHERE rltbl_user_id = #{userId}
            ),
            a.status,
            a.last_update
        FROM
            ACCOUNT_TBL a, ROLE_TBL r
        WHERE
            a.user_id = #{userId}
            AND a.user_id = r.rltbl_user_id
    ]]>
    <'/select>
 
----------
             
    <'resultMap id="accountMap" type="account.master.system.pilot.domain.model.Account">
        <'id property="userId" column="user_id" />
        <'result property="firstName" column="first_name" />
        <'result property="lastName" column="last_name" />
        <'result property="status" column="status" />
        <'result property="lastUpdate" column="last_update" />
        <'result property="roles" javaType="java.util.List" resultMap="mapForPropRoles" />
    <'/resultMap>
    <'resultMap id="mapForPropRoles" type="java.lang.String">
        <'result property="roles" column="role_column" jdbcType="VARCHAR" javaType="java.lang.String" />
    <'/resultMap>
             
----------
 
    <'resultMap id="accountMap" type="account.master.system.pilot.domain.model.Account">
        <'id property="userId" column="user_id" />
        <'result property="firstName" column="first_name" />
        <'result property="lastName" column="last_name" />
        <'result property="status" column="status" />
        <'result property="lastUpdate" column="last_update" />
        <'collection property="roles" column="userId" javaType="ArrayList" ofType="String" select="findUserRoles">
            <'result property="value" column="role_column"/>
        <'/collection>
    <'/resultMap>
 
                  <'select id="findUserRoles" resultType="String">
                  <'![CDATA[
                      SELECT
                          role as role_column
                      FROM
                          ROLE_TBL
                      WHERE
                         rl_user_id = #{userId}
                  ]]>
    <'/select>
 
----------
 
ref.
http://mybatis.org//dtd/mybatis-3-mapper.dtd
Mybatis resultmap to map values to hash map field of a model, stckoverflow, Dec 6 '12 at 16:46
http://stackoverflow.com/questions/13548349/mybatis-resultmap-to-map-values-to-hash-map-field-of-a-model
https://github.com/mybatis/mybatis-3/issues/364
http://stackoverflow.com/questions/1127992/how-do-you-map-a-liststring-in-ibatis
ネストされた select を使って collection を読み込む
http://www.mybatis.org/mybatis-3/ja/sqlmap-xml.html
Nested Select for Collection
http://www.mybatis.org/mybatis-3/sqlmap-xml.html
 
tag:
ORM MyBatis iBatis nested list string resultmap collecon BuilderException SAXParseException 1:N

tag : ORM MyBatis iBatis nested list string resultmap collecon BuilderException SAXParseException

2017-03-29 23:04 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] Spring related troubles faced in March, 2017

------------------------------
## 1       
tag: spring-security NoSuchBeanDefinitionException     
 
open-date: 2017/3/13          
trouble:
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'userDetailsService' is defined          
 
close-date: 2017/3/13         
shooting:
spring-security.xml
    <'sec:authentication-manager>
        <'sec:authentication-provider user-service-ref="userDetailsService">
            <'sec:password-encoder ref="passwordEncoder" />
        <'/sec:authentication-provider>
    <'/sec:authentication-manager>
userDetailsService
 
UserDetailServiceImpl implements UserDetailsService としていた為、bean名が合致していなかった。
HogeRepositoryをInjectする時は、Interface名でautowiredされてるのと混同してた。ココは普通のref-beanなので真面目なbean名が正解。
 
 
------------------------------
## 2       
tag: spring-security jsp form-login     
 
open-date: 2017/3/13          
trouble:
http://localhost:8080/myProject/login.jsp
Resource Not Found Error!
Resource not found.
 
close-date: 2017/3/13         
shooting:
        <'sec:form-login
            login-page="/login.jsp"
            authentication-failure-url="/login.jsp?error=true" />
としてたのを、以下に修正
        <'sec:form-login
            login-page="/login/loginForm"
            login-processing-url="/login" />
実際のjspは「webapp/WEB-INF/views/login/loginForm.jsp」
 
 
------------------------------
## 3       
tag: spring-security jsp NotReadablePropertyException 
 
open-date: 2017/3/13          
trouble:
NotReadablePropertyException: Invalid property 'principal.account' of bean class [org.springframework.security.authentication.AnonymousAuthenticationToken]: Bean property 'principal.account' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?             
 
close-date: 2017/3/13         
shooting:
JSPで
<'sec:authorize access="isAuthenticated()">
せずに
${f:h(principal.account.firstName)}
した為の例外
 
 
------------------------------
## 4       
tag: jsp CannotRenderException       
 
open-date: 2017/3/13          
trouble:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.apache.tiles.request.render.CannotRenderException: An exception occurred processing JSP page /WEB-INF/views/layout/template.jsp at line 27
Caused by: org.apache.jasper.JasperException: /WEB-INF/views/login/loginForm.jsp (line: 4, column: 4) プレフィックス tでインポートされたタグライブラリには、タグ messatePanel は存在しません
 
close-date: 2017/3/13         
shooting:
凡ミス。スペルミス
t:messatePanel --> t:messagesPanel
 
 
------------------------------
## 5       
tag: jsp JasperException    
 
open-date: 2017/3/13          
trouble:
Caused by: org.apache.jasper.JasperException: /WEB-INF/views/login/loginForm.jsp (line: 4, column: 62) Attribute qualified names must be unique within an element          
 
close-date: 2017/3/13         
shooting:
<'t:messagesPanel messagesType="error" messagesType="error" messagesAttributeName="SPRING_SECURITY_LAST_EXCEPTION" />
messagesTypeが重複している。↓↓TOBE
<'t:messagesPanel messagesType="error" messagesAttributeName="SPRING_SECURITY_LAST_EXCEPTION" />
 
 
------------------------------
## 6       
tag: spring-security InternalAuthenticationServiceException          
 
open-date: 2017/3/13          
trouble:
spring-securityの認証項目をusernameでなくuserIdにしたい。
org.springframework.security.authentication.InternalAuthenticationServiceException: For input string: ""
at org.springframework.security.authentication.dao.DaoAuthenticationProvider.retrieveUser(DaoAuthenticationProvider.java:126)
Caused by: java.lang.NumberFormatException: For input string: ""
at account.master.system.pilot.domain.service.userdetails.AmspUserDetailsServiceImpl.loadUserByUsername(AmspUserDetailsServiceImpl.java:29)
 
close-date: 2017/3/13         
shooting:
loginForm.jspのinputのname/idはusernameにするか、小細工が要る。
AFTER:
            <'td><'input type="text" id="username" name="username" value="0001" />(0001)<'/td>
            <'!-- <'td><'input type="text" id="userId" name="userId" value="0001" />(0001)<'/td> -->
もしくは、
JSP ・・・ <'td><'input type="text" id="userId" name="userId" value="0001" />(0001)<'/td>
spring-security.xml ・・・
<'sec:form-login
    login-page="/login/loginForm"
    login-processing-url="/login"
    username-parameter="userId"/>
 
ref.
Spring Security Custom Login Form Annotation Example
https://www.mkyong.com/spring-security/spring-security-custom-login-form-annotation-example/
Spring Bootで認証を行う
http://blog.okazuki.jp/entry/2015/07/05/180726
 
 
------------------------------
## 7       
tag: spring-security TypeException    
 
open-date: 2017/3/13          
trouble:
spring-securityの認証項目をusernameでなくuserIdにしたい。
Caused by: org.apache.ibatis.type.TypeException: Could not set parameters for mapping: ParameterMapping{property='userId', mode=IN, javaType=class java.lang.String, jdbcType=null, numericScale=null, resultMapId='null', jdbcTypeName='null', expression='null'}. Cause: org.apache.ibatis.type.TypeException: Error setting non null for parameter #1 with JdbcType null . Try setting a different JdbcType for this parameter or a different configuration property. Cause: java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
 
close-date: 2017/3/13         
shooting:
なんか術あるんだろうけど、そりあえずの強行手段。 int 型をしぶしぶ String 型に定義しなおす
 
BEFORE
CREATE TABLE ACCOUNT_TBL (
    user_id int(4),
AFTER
CREATE TABLE ACCOUNT_TBL (
    user_id varchar(4),
 
 
------------------------------
## 8       
tag: Git  
 
open-date: 2017/3/14          
trouble:
git  push済みのcommitを揉み消したい      
 
close-date: 2017/3/14         
shooting:
get reset HEAD~
git push -f origin branchname
 
HEADの後の「~」が「直前の」コミットを意味する。2こ前のコミットを指したければ「~~」とする感じ。
 
ref.
git pushを取り消す
http://tweeeety.hateblo.jp/entry/2015/06/10/215753
さっきの取り消したい!って時のGitコマンドまとめ
http://qiita.com/kansiho/items/2bacecdb95d752cb38b7
 
 
------------------------------
## 9       
tag: jsp checkbox NestedServletException CannotRenderException           
 
open-date: 2017/3/14          
trouble:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.apache.tiles.request.render.CannotRenderException: java.io.IOException: JSPException including path '/WEB-INF/views/user/registerForm.jsp'.
Caused by: java.io.IOException: JSPException including path '/WEB-INF/views/user/registerForm.jsp'.
Caused by: org.apache.jasper.JasperException: /WEB-INF/views/user/registerForm.jsp (line: 40, column: 16) TLDに従ってタグ form:checkbox は空でなければいけませんが、そうではありません
 
close-date: 2017/3/14         
shooting:
<'form:checkbox path="status" label="ACTV" >ACTV<'/form:checkbox>
↓↓
<'form:checkbox path="status" label="ACTV" />
 
 
------------------------------
## 10     
tag: Spring MVC IllegalStateException            
 
open-date: 2017/3/14          
trouble:
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'userForm' available as request attribute   
 
close-date: 2017/3/14         
shooting:
Controllerで以下を実装する。
@ModelAttribute
public UserForm setUpForm() {
  UserForm form = new UserForm();
  return form;
}
 
 
------------------------------
## 11     
tag: Spring AOP BeanCreationException BeanCreationException NoSuchBeanDefinitionException        
 
open-date: 2017/3/14          
trouble:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'registerController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: account.master.system.pilot.domain.service.user.RegisterService account.master.system.pilot.app.user.RegisterController.registerService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [account.master.system.pilot.domain.service.user.RegisterService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@javax.inject.Inject()}
 
 
close-date: 2017/3/14         
shooting:
public class RegisterServiceImpl implements RegisterService {
↓↓
@Service
public class RegisterServiceImpl implements RegisterService {
 
 
------------------------------
## 12     
tag: jsp JasperException    
 
open-date: 2017/3/14          
trouble:
Caused by: org.apache.jasper.JasperException: /WEB-INF/views/user/registerForm.jsp (line: 10, column: 39) ${ タグが終了していません             
 
close-date: 2017/3/14         
shooting:
<'td><'form:input path="userId" />${f:h{userForm.userId)}<'/td>
↓↓ f:h"{" の括弧が合ってない
<'td><'form:input path="userId" />${f:h(userForm.userId)}<'/td>
 
 
------------------------------
## 13     
tag: jsp checkbox IllegalArgumentException    
 
open-date: 2017/3/14          
trouble:
Caused by: java.lang.IllegalArgumentException: Attribute 'value' is required when binding to non-boolean values  
 
close-date: 2017/3/14         
shooting:
<'form:checkbox path="status" label="INIT" />
↓↓
<'form:checkbox path="status" label="INIT" value="INIT" />
 
 
------------------------------
## 14     
tag: Spring MVC RequestMapping UnsatisfiedServletRequestParameterException    
 
open-date: 2017/3/14          
trouble:
<'form:form action="${pageContext.request.contextPath}/user/register"
method="post" modelAttribute="userForm">
<'form:button>Confirm<'/form:button>
<'/form:form>
 
org.springframework.web.bind.UnsatisfiedServletRequestParameterException: Parameter conditions "redo" OR "complete" OR "form" OR "confirm" not met for actual request parameters: register={Submit}, _csrf={c2007699-7c1a-482c-81fc-11858d0cb42f}
 
close-date: 2017/3/14         
shooting:
@Controller
@RequestMapping(value = "/user/register")
public class RegisterController {
public String register(@Valid UserForm userForm, BindingResult bindingResult, Model model, RedirectAttributes attributes) {
↓↓RequestMappingの定義がメソッドに無かった。
@RequestMapping
public String register(@Valid UserForm userForm, BindingResult bindingResult, Model model, RedirectAttributes attributes) {
 
 
------------------------------
## 15     
tag: "spring DateTimeFormat
typeMismatch Date ConversionFailedException
 
open-date: 2017/3/14          
trouble:
Field error in object 'userForm' on field 'birthday': rejected value []; codes [typeMismatch.userForm.birthday,typeMismatch.birthday,typeMismatch.java.util.Date,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [userForm.birthday,birthday]; arguments []; default message [birthday]]; default message [Failed to convert property value of type [java.lang.String] to required type [java.util.Date] for property 'birthday'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.util.Date] for value ''; nested exception is java.lang.IllegalArgumentException]  
 
close-date: 2017/3/14         
shooting:
以下のようにformatterを噛ませば良い。
 
@NotNull
@DateTimeFormat(pattern = "yyyy/MM/dd")
private Date birthday;//birthday
 
 
------------------------------
## 16     
tag: Spring redirect RedirectAttributes             
 
open-date: 2017/3/14          
trouble:
Resource Not Found Error!
Resource not found.
 
close-date: 2017/3/14         
shooting:
return "redirect:user/register?complete";
↓↓
return "redirect:/user/register?complete";
 
 
------------------------------
## 17     
tag: xml util schema           
 
open-date: 2017/3/14          
trouble:
Description Resource Path Location Type
The prefix "util" for element "util:map" is not bound. myproject-codelist.xml /myproject-domain/src/main/resources/META-INF/spring line 29 XML Problem
 
 
close-date: 2017/3/14         
shooting:
xmlの冒頭にschema定義にutilを追加する
 
<'beans xmlns=
    xmlns:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
    ">
 
 
------------------------------
## 18     
tag: TERASOLUNA SimpleMapCodeList          
 
open-date: 2017/3/14          
trouble:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'org.terasoluna.gfw.common.codelist.SimpleMapCodeList' is defined         
 
close-date: 2017/3/14         
shooting:
<'bean id="CL_ROLE" parent="org.terasoluna.gfw.common.codelist.SimpleMapCodeList">
↓↓
<'bean id="CL_ROLE" class="org.terasoluna.gfw.common.codelist.SimpleMapCodeList">
 
cf. DBから取得する場合は「parent="AbstractJdbcCodeList"」とparentでOK
 
 
------------------------------
## 19     
tag: Spring xml IllegalArgumentException ClassNotFoundException           
 
open-date: 2017/3/14          
trouble:
Caused by: java.lang.IllegalArgumentException: Cannot find class [java.util.linkedHashMap]
Caused by: java.lang.ClassNotFoundException: java.util.linkedHashMap
 
close-date: 2017/3/14         
shooting:
単なるミスペル
 
<'util:map key-type="java.lang.String" value-type="java.lang.String"
map-class="java.util.linkedHashMap">
↓↓
map-class="java.util.LinkedHashMap">
 
 
------------------------------
## 20     
tag: Spring MVC DefaultMessageSourceResolvabl        
 
open-date: 2017/3/15          
trouble:
org.springframework.context.support.DefaultMessageSourceResolvable: codes [userForm.birthday,birthday]; arguments []; default message [birthday]         
 
close-date: 2017/3/15         
shooting:
JSP では text で受けているのに対し、Form は Date 型で宣言している為。
Form の方を String にすれば良し。
 
 
------------------------------
## 21     
tag: Spring MVC  
 
open-date: 2017/3/15          
trouble:
form の validation の NotNull を通過してしまう、無入力でsubmitしているのに。          
 
close-date: 2017/3/15         
shooting:
無入力でも空文字が渡っている為。NotBlankなvalidationも付ければ良い。
 
 
------------------------------
## 22     
tag: Spring MVC validation 
 
open-date: 2017/3/16          
trouble:
4文字以上って設定しただけなのに、エラーメッセージが「size must be between 4 and 2147483647」と出る。
2147483647 は最大値と思われる。
 
close-date: 2017/3/16         
shooting:
@Size(min = 4)
private String password;//password
としていた為の事象。Sizeでやるなら @Size(min=4, max=8)な書き方にすべき。
最小値だけの指定であれば↓以下が正解
@Min(value = 4)
private String password;//password
というか、数値じゃなくて文字列数なのでMinも違う説w
文字列数はSizeで良いぽい。

tag : Spring

2017-03-23 22:02 : 開発 : コメント : 0 : トラックバック : 0 :

[道具] ローカルメモリを極力使わずに済む開発環境が欲しい

検討用備忘録

条件:
無料、Java、軽量 or クラウド、(可能なら) Windows

[候補] Eclipse v3.5
http://mergedoc.osdn.jp/pleiades-redirect/3.5/pleiades_platform_jre.zip.html
ref.
Eclipseで最軽量Java開発環境を構築
https://www.erestage.com/develop/eclipse_mini/

tag : Eclipse IDE Java

2017-03-09 20:26 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] gitignore な話

.gitignore
 
# Java
*.class
*.jar
*.war
*.ear
 
# Eclipse
.project
.classpath
.settings
 
# Idea
.idea
*.iml
*.iws
*.ipr
 
# OS
Thumbs.db
.DS_Store
 
# Gradle
.gradle
!gradle-wrapper.jar
 
# Maven
target
 
# Build
out
build
bin
 
# Other
*.log
*.swp
*.bak
 
 
ref.
Javaのプロジェクトで使う.gitignore
http://qiita.com/tora470/items/d61c3fcb261e48edc996

tag:
git gitignore java

tag : git gitignore java

2017-03-09 19:46 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] GitBushで保存されているアカウント情報を変更する

GitBushで保存されているアカウント情報
=コミットログ↓↓に残るユーザ名とメールアドレス
 
$ git log
commit 4d8687b040093addb8c59960836384b0f5767776
Author: hogehoge
Date:   Thu Aug 5 20:05:20 2010 +0900
 
 
既存の設定を確認する @GitBush
以下のいずれでも可
globalとlocalがある
$ git config -l
$ git config --global –list
$ $git config --local --list
 
 
アカウント情報の設定
 
■方法① configコマンドで変更する @GitBush
$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.com
 
■方法② 設定ファイルを直に変更する
GitのHOMEディレクトリの在り処を確認する @GitBush
$ git ~
 
そのフォルダに行くと、「.gitconfig」がある
それをeditorで開くと以下のような記載がある筈
それをよしなに変更して保存する
 
[user]
              name = John Doe
              email = johndoe@example.com
 
 
● cf. -諸々な設定ファイル
system設定
[gitインストール先]\etc\gitconfig
※Linuxの場合は、/etc/gitconfig
 
global設定
C:\Users\$USER\.gitconfig
又は
C:\Documents and Settings\$USER\.gitconfig
※Linuxの場合は、${HOME}/.gitconfig
 
リポジトリ設定
gitリポジトリ\.git\config
 
● cf. -SourceTree にも同様な設定あり
global設定
SourceTreeのメニュー [ツール]-[オプション]
リポジトリ設定
SourceTreeのメニュー [リポジトリ]-[リポジトリ設定]の[詳細]タブ
 
 
ref.
1.5 使い始める - 最初のGitの構成
https://git-scm.com/book/ja/v1/%E4%BD%BF%E3%81%84%E5%A7%8B%E3%82%81%E3%82%8B-%E6%9C%80%E5%88%9D%E3%81%AEGit%E3%81%AE%E6%A7%8B%E6%88%90
gitのauthorの確認と変更
http://hacknote.jp/archives/15745/
git設定ファイルの構成について
http://zero-config.com/windows/git-config.html
 
 
tag:
git GitHub GitBush author config

tag : git GitHub GitBush author config

2017-03-09 19:33 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] SonarQube Cyclomatic Complexity 循環的複雑度

SonarQube が出す「複雑度」って何よ?
 
で、Complexityって何よ?
循環的複雑度 (Cyclomatic Complexity; CC) ゆうもの。
条件複雑度(Conditional Complexity)とも呼ばれるそう。CCであることには変わらないww
Javaの場合、if, for, while, case, catch, throw, return 構文で考えられる処理分岐の回数を言う。
それら情報を魔法の方式 (M = E − N + 2P) に当てはめて算出される数字。
# つまり、Complexity とは別に出されている 重複 (Duplication) の数値が高い内は、複雑度は見てもしょうがない
気がする。
 
で、一般的に言われるのは
 ・ 1-4 優秀!
 ・ 5-7 可
 ・ 8-10 不可
 ・ 11+ 論外
 
 
その複雑度を下げる為にできる事
 
モノゴトはシンプルにせよ:
- easy to read
- easy to use
- easy to change
- no use of any non-necessary third party tool or technology
- looks simple
- lean
- straightforward
 
基本規則を遵守せよ:
- keep methods short (one screen limit)
- never ever reuse a variable for different purpose
- use self-descriptive variable and method names
- no magic numbers
- be friend with your language
- dont fight the convention
- watch out for premature optimization
- always refactor the code after you test it
- dont get sucked into over-engineering
- learn new things by prototyping
 
 
Metric Definitions
https://docs.sonarqube.org/display/SONAR/Metric+Definitions
Metrics - Complexity
https://docs.sonarqube.org/display/SONAR/Metrics+-+Complexity
Through the eyes of sonar : Complexity
https://mestachs.wordpress.com/2012/11/26/through-the-eyes-of-sonar-complexity/
循環的複雑度
https://ja.wikipedia.org/wiki/%E5%BE%AA%E7%92%B0%E7%9A%84%E8%A4%87%E9%9B%91%E5%BA%A6

tag:
SonarQube Cyclomatic Complexity 循環的複雑度
 

tag : SonarQube Cyclomatic Complexity 循環的複雑度

2017-03-07 21:15 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] Spring での責務

偶然見つけたけど分かり易いの備忘

Spring での責務


ref.
Spring での責務についてまず見てほしい一枚の絵
http://qiita.com/yo1000/items/a6acbf5f454a7f53aef9

tag.
Java Spring View Controller Service Repository Template Model Advice AOP

tag : Java Spring View Controller Service Repository Template Model Advice AOP

2017-03-04 12:29 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] SonarQube なる CodeChecker

tag: SonarQube Scanner SonarLint PostgreSQL IllegalStateException HeapDumpOutOfMemoryError

// ------------------------------------------------------------
■ quick reference: // 詳細は後述参照

step 0 (optional)
> install Sonar
> set a database for sonar
> start Sonar

step 1
create a folder to keep the target source
e.g. C:\tmp\Sonar\testTargetProject

step 2
create sonar-project.properties, save it under the same folder.
e.g. C:\tmp\Sonar\testTargetProject\sonar-project.properties

step 3
start Sonar, and start check via a CommandPrompt
cd C:\sonar\sonarqube\bin\windows-x86-64
StartSonar.bat
cd C:\_btkouei\20170626_泉岳寺のSonar\target
sonar-scanner.bat

step 4
check the result
http://localhost:9000/about

------------------------------------------------------------ //
 
SonarQubeとは
スイスのSonarSource社が主に開発を行っている
統合的なプログラム品質管理を行える統合品質管理ツール (無償)
https://www.sonarqube.org
 
■ できるとこと
ソースコードの静的解析チェック
プログラムの複雑度の測定
諸々解析結果はブラウザから閲覧
結果のエクセルなりにexportもできる
CI環境への組み込みも可
 
■ 対応言語
いろいろ
 
■ 使い方
 
SonarQube Server
解析結果を表示するサーバ
https://www.sonarqube.org から zip を DL
sonarqube-6.2.zip を展開して、Cドライブに移植
cd C:\sonar\sonarqube\bin\windows-x86-64
 
DB の設定
コマンドプロンプトを開き以下を実行してく
"C:/Program Files/PostgreSQL/9.4/bin/psql" postgres postgres
# postgresユーザのPWを入力
password
# sonarqubeユーザを新規作成
CREATE USER sonarqube WITH PASSWORD 'sonarqube';
ALTER ROLE sonarqube CREATEDB;
# 権限付与
CREATE DATABASE sonar WITH ENCODING 'UTF-8' OWNER=sonarqube;
grant all privileges on database sonar to sonarqube;
# 既存ユーザの確認
\du
\l
# RackInitializationException 回避の為のサーチパスの設定
ALTER USER sonarqube SET search_path to public;
# ログアウト
\q
 
諸項目の設定
C:\sonar\sonarqube\conf\sonar.properties
上記プロパティファイルの当該箇所を以下のように更新
# User credentials.
sonar.jdbc.username=sonarqube
sonar.jdbc.password=sonarqube
#----- PostgreSQL 8.x/9.x
sonar.jdbc.url=jdbc:postgresql://localhost/sonar
 
StartSonar.bat でSonarQubeサーバを起動
http://localhost:9000/ にアクセス
管理ユーザの場合は admin / admin がデフォルト Login ID と PW
 
cf.
InstallNTService.bat             サービスとしてインストール
StartNTService.bat サービスの開始
StopNTService.bat              サービスの停止
UninstallNTService.bat         サービスのアンインストール
 
// ------------------------------
[事象]
StartSonar.bat で HeapDumpOutOfMemoryError
C:\sonar\sonarqube\logs\es.log に詳細あり
詳細
2017.03.02 14:35:17 WARN  es[][o.s.p.ProcessEntryPoint] Fail to start es
org.elasticsearch.transport.BindTransportException: Failed to bind to [9001]
org.elasticsearch.transport.BindTransportException: Failed to bind to [9001]
              at org.elasticsearch.transport.netty.NettyTransport.bindToPort(NettyTransport.java:478)
Caused by: org.jboss.netty.channel.ChannelException: Failed to bind to: /127.0.0.1:9001
              at org.jboss.netty.bootstrap.ServerBootstrap.bind(ServerBootstrap.java:272)
Caused by: java.net.BindException: Address already in use: bind
              at sun.nio.ch.Net.bind0(Native Method)
 
[原因]
先に実行した奴のプロセスが残ってて、portを取り合ってるため。
ついでがあったのでPC再起動してやったら普通に軌道できた
------------------------------ //
 
 
SonarQube Scanner
ソース解析して、結果をSonarQubeサーバに送る子
他にmavenプラグインを使用する等、代替手段あり
https://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner
から sonar-scanner-2.8.zip DL
展開して、、Cドライブに移植>C:\sonar\sonar-scanner
 
環境変数Pathに「C:\sonar\sonar-scanner\bin」を追加
コマンドプロンプトで以下を叩いてインストールされてることを確認
sonar-scanner.bat -h
諸々と情報が表示されればOK
 
諸項目の設定
分析したいプロジェクトのフォルダ配下に「sonar-project.properties」を新規に作成
各項目は以下を参照
https://docs.sonarqube.org/display/SONAR/Analysis+Parameters
記載内容例:
// --------------------
# must be unique in a given SonarQube instance
sonar.projectKey=my:project
# this is the name and version displayed in the SonarQube UI. Was mandatory prior to SonarQube 6.1.
sonar.projectName=My project
sonar.projectVersion=1.0

# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows.
# Since SonarQube 4.2, this property is optional if sonar.modules is set.
# If not set, SonarQube starts looking for source code from the directory containing
# the sonar-project.properties file.
sonar.sources=.

# Encoding of the source code. Default is default system encoding
#sonar.sourceEncoding=UTF-8
-------------------- //
 
作成した「sonar-project.properties」と同じ階層までコマンドプロンプトで cd していき
そこで「sonar-scanner.bat」を実行して分析開始。
※ sonar-runner.bat はかつて使われてた非推奨な輩
こんなんのが最後に表示される筈↓↓
INFO: More about the report processing at http://localhost:9000/api/ce/task?id=AVqOBVe9614YH3R8UGOd
INFO: Task total time: 13:47.217 s
INFO: ------------------------------------------------------------------------
INFO: EXECUTION SUCCESS
INFO: ------------------------------------------------------------------------
INFO: Total time: 13:48.934s
INFO: Final Memory: 57M/926M
INFO: ------------------------------------------------------------------------
 
http://localhost:9000/ に行き、admin / admin でログイン
対象のプロジェクトまで掘ってくと結果が見れる
 
 
SonarLint
http://www.sonarlint.org/
Eclipse上で静的チェックしてくれる子
結果はSonarQubeへ送付するも、localで確認するも可
条件:
Java 8, SonarQube 5.6+
 
org.sonarlint.eclipse.site-2.6.0.201702201416.zip をDLして展開
org.sonarlint.eclipse.site-2.6.0.201702201416 を、
C:\STS\sts-bundle\sts-3.8.2.RELEASE\plugins に配置
STS を再起動
してみたけど、「SonarQube server view」が無い、、
 
「Views Plugin - Plugins - SonarQube」が必要らしいというのはもはや昔の話で
コレ ↓↓ を入れろ、ってことぽい
https://www.sonarsource.com/why-us/products/plugins/governance.html
が、これ有償なお代物..
ん?これ? ↓↓ よく分からん。
https://docs.sonarqube.org/display/PLUG/Views
https://docs.sonarqube.org/display/PLUG/Governance+Plugin
 
 
ref.
SonarQubeでプログラムの品質管理をはじめる(概要)
http://qiita.com/sh-ogawa/items/fac0eca110c3558dfae9
Analyzing with SonarQube Scanner <-- 日本語サイト漁ったけど、結局、これが最も明快だった、、
https://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner
オカルトから科学へ - SonarQubeで静的コード解析を始めよう
http://koduki.hatenablog.com/entry/2014/02/11/133558
SONNARQUBEでソースコードの品質を解析する
https://t246osslab.wordpress.com/2016/11/20/sonnarqube%E3%81%A7%E3%82%BD%E3%83%BC%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%89%E3%81%AE%E5%93%81%E8%B3%AA%E3%82%92%E8%A7%A3%E6%9E%90%E3%81%99%E3%82%8B/
SonarQubeをインストール
http://gozuk16.hatenablog.com/entry/2016/04/15/171138
コード探知機「Sonar」でプロジェクトの深海を探れ! (2/4)
http://www.atmarkit.co.jp/ait/articles/1010/08/news124_2.html
SonarQube, C++ プラグインの Windows へのインストールと使い方
http://yohshiy.blog.fc2.com/blog-entry-305.html
SonnarQubeを使って有名どころJavaフレームワークの品質を解析してみた
http://daipresents.com/2016/sonnarqube/

tag : SonarQube Scanner SonarLint PostgreSQL IllegalStateException HeapDumpOutOfMemoryError

2017-03-03 08:33 : 開発 : コメント : 0 : トラックバック : 0 :
ホーム  次のページ »

search

ad



counter


tag cloud

category cloud