<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>struts2 &#8211; blog.fukata.org</title>
	<atom:link href="/archives/tag/struts2/feed/" rel="self" type="application/rss+xml" />
	<link>/</link>
	<description>旅するプログラマ</description>
	<lastBuildDate>Fri, 11 Aug 2017 23:07:14 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=5.6</generator>
	<item>
		<title>[JC]改行コードをbrタグに置換するタグライブラリを作成しました</title>
		<link>/archives/1444/</link>
					<comments>/archives/1444/#respond</comments>
		
		<dc:creator><![CDATA[fukata]]></dc:creator>
		<pubDate>Wed, 29 Jul 2009 16:10:42 +0000</pubDate>
				<category><![CDATA[開発]]></category>
		<category><![CDATA[JCommunity]]></category>
		<category><![CDATA[struts2]]></category>
		<category><![CDATA[taglib]]></category>
		<guid isPermaLink="false">http://fukata.org/?p=1444</guid>

					<description><![CDATA[はい。タイトル通りのタグライブラリを作成してみました。当初普通のJSPのタグライブラリを作成したのですが、下記のように値を渡す予定だったのですが、これじゃ渡せないじゃんということに作成し終わった後に気 ... <a href="/archives/1444/"> 続きを読む</a>]]></description>
										<content:encoded><![CDATA[<p>はい。タイトル通りのタグライブラリを作成してみました。当初普通のJSPのタグライブラリを作成したのですが、下記のように値を渡す予定だったのですが、これじゃ渡せないじゃんということに作成し終わった後に気づいて作成しなおしました。というか、デバッグの始まりでしたw</p>
<pre lang="JSP">
<jc :txt2br value="%{messageDto.body}"></jc>
</pre>
<p>今回作成したのは下記の4点です。</p>
<ul>
<li>Text2BrTag.java：タグライブラリクラス</li>
<li>Text2Br.java：タグライブラリコンポーネント</li>
<li>HtmlUtils.java：HTML出力用ユーティリティ</li>
<li>jcommunity.tld：カスタムタグ定義ファイル</li>
</ul>
<p>また今回も醜いかとは思いますが、何かの役に立てばと思い、ソースを貼り付けておきます。</p>
<p><span id="more-1444"></span></p>
<div class="ad_section"><div class="ad_title">広告</div><div class="ad_body"><script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- blog-content-bottom1 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-9703571485671477"
     data-ad-slot="4353022998"
     data-ad-format="auto"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script></div></div>
<p>■Text2BrTag.java</p>
<pre lang="JAVA" line="1">
package org.fukata.jc_common.view.taglib;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts2.components.Component;
import org.apache.struts2.views.jsp.ComponentTagSupport;
import org.fukata.jc_common.view.component.Text2Br;

import com.opensymphony.xwork2.util.ValueStack;

/**
 * テキストの改行コードを<br />に置換する
 * 
 * @author tatsuya
 *
 */
public class Text2BrTag extends ComponentTagSupport {
	
	private static final long serialVersionUID = 1L;
	
	// 置換する文字列
	private String value;
	
	public String getValue() {
		return value;
	}

	public void setValue(String value) {
		this.value = value;
	}

	@Override
	public Component getBean(ValueStack stack, HttpServletRequest req,
			HttpServletResponse res) {
		return new Text2Br(stack);
	}
	
	@Override
	protected void populateParams() {
		super.populateParams();
		
		Text2Br text2Br = (Text2Br) component;
		text2Br.setValue(this.value);
	}

	
}
</pre>
<p>■Text2Br.java</p>
<pre lang="JAVA" line="1">
package org.fukata.jc_common.view.component;

import java.io.IOException;
import java.io.Writer;

import org.apache.struts2.components.Component;
import org.fukata.jc_common.utils.HtmlUtils;

import com.opensymphony.xwork2.util.ValueStack;

public class Text2Br extends Component {

	private String value;
	
	public Text2Br(ValueStack stack) {
		super(stack);
	}
	
	@Override
	public boolean start(Writer writer) {
		boolean result = super.start(writer);
		
		if (this.value!=null) {
			this.value = findString(this.value);
			// 改行コードをbrタグに置換
			this.value = HtmlUtils.getTxt2Br(this.value);
		}
		
		return result;
	}
	
	@Override
	protected boolean end(Writer writer, String body, boolean popComponentStack) {
		boolean result = super.end(writer, body, popComponentStack);
		
		try {
			// 画面に書き出す
			writer.write(this.value);
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		return result;
	}

	public String getValue() {
		return value;
	}

	public void setValue(String value) {
		this.value = value;
	}

	
}
</pre>
<p>■HtmlUtils.java</p>
<pre lang="JAVA" line="1">
package org.fukata.jc_common.utils;

public class HtmlUtils {
	
	private static final String BKREAK_REGEX = "(\r\n|\r|\n)"; 
	private static final String HTML_BREAK = "<br />"; 
	
	private HtmlUtils() {
	}
	
	public static String getTxt2Br(String txt) {
		return txt.replaceAll(BKREAK_REGEX, HTML_BREAK);
	}
}
</pre>
<p>■jcommunity.tld</p>
<pre lang="XML" line="1">
< ?xml version="1.0" ?>
< !DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "https://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">

<taglib xmlns="https://java.sun.com/xml/ns/j2ee"
        xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="https://java.sun.com/xml/ns/j2eeweb-jsptaglibrary_2_0.xsd"
        version="2.0">
  <tlibversion>1.0</tlibversion>
  <jspversion>2.0</jspversion>
  <shortname>jcommunity</shortname>
  <info>JCommunity tab library</info>

  <tag>
    <name>txt2br</name>
    <tagclass>org.fukata.jc_common.view.taglib.Text2BrTag</tagclass>
    <bodycontent>empty</bodycontent>
    <info>text to html br tag</info>
    <attribute>
    	<name>value</name>
    	<required>true</required>
    	<rtexprvalue>true</rtexprvalue>
    	<description>< ![CDATA[Value expression for Parameter to set]]&gt;</description>
    </attribute>
  </tag>
</taglib>
</pre>
]]></content:encoded>
					
					<wfw:commentRss>/archives/1444/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>[JC]Struts2での例外処理について</title>
		<link>/archives/1429/</link>
					<comments>/archives/1429/#respond</comments>
		
		<dc:creator><![CDATA[fukata]]></dc:creator>
		<pubDate>Sat, 25 Jul 2009 00:32:39 +0000</pubDate>
				<category><![CDATA[開発]]></category>
		<category><![CDATA[JCommunity]]></category>
		<category><![CDATA[struts2]]></category>
		<guid isPermaLink="false">http://fukata.org/?p=1429</guid>

					<description><![CDATA[ActionなどでExceptionが発生した際に、自動的にエラーページに遷移できるようにしておくと余計なエラー処理を内部で各必要がなくなるので便利かと思い作成しました。 今回の要件として、上記に加え ... <a href="/archives/1429/"> 続きを読む</a>]]></description>
										<content:encoded><![CDATA[<p><a href="https://farm6.static.flickr.com/5019/5475643477_903f716249_m.jpg" target="_blank" title="ExceptionSequence"><img loading="lazy" src="https://farm6.static.flickr.com/5019/5475643477_903f716249_m.jpg" alt="ExceptionSequence" width="200" height="150" class="attachment wp-att-1430 alignleft" /></a>ActionなどでExceptionが発生した際に、自動的にエラーページに遷移できるようにしておくと余計なエラー処理を内部で各必要がなくなるので便利かと思い作成しました。</p>
<p>今回の要件として、上記に加え、エラーの内容をメッセージコードで管理しているのでそれを利用し、さらに意図しないエラーの場合はデフォルトのメッセージコードを割り当てるというものです。</p>
<p>作成したのは、「<strong>com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor</strong>」を継承した自作例外インターセプタークラスだけです。実際、処理もほとんど変わっていません。</p>
<p>いつもの用に作成したソースは、下記に掲載しているので良ければ見てください。</p>
<p>作成したクラス以外の注意点として、インターセプタースタックにデフォルトの「defaultStack」を利用している場合、exceptionという通常の例外処理用インターセプターが存在するため、それを除外する必要があります。定義済みのスタックから除外する方法が見つからなかったので、defaultStackからexceptionを除いてstruts.xmlにて再定義しています。</p>
<p><span id="more-1429"></span></p>
<div class="ad_section"><div class="ad_title">広告</div><div class="ad_body"><script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- blog-content-bottom1 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-9703571485671477"
     data-ad-slot="4353022998"
     data-ad-format="auto"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script></div></div>
<p>■JcExceptionInterceptor</p>
<pre lang="java" line="1">
package org.fukata.jc_common.interceptor;

import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.fukata.jc_common.exception.JcSystemException;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.config.entities.ExceptionMappingConfig;
import com.opensymphony.xwork2.interceptor.ExceptionHolder;
import com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor;

public class JcExceptionInterceptor extends ExceptionMappingInterceptor {

	private static final long serialVersionUID = 1L;
	
	protected String defaultMessageCode;
	
	public String getDefaultMessageCode() {
		return defaultMessageCode;
	}

	public void setDefaultMessageCode(String defaultMessageCode) {
		this.defaultMessageCode = defaultMessageCode;
	}

	@Override
	public String intercept(ActionInvocation invocation) throws Exception {
        String result;

        try {
            result = invocation.invoke();
        } catch (Exception e) {
            if (isLogEnabled()) {
                handleLogging(e);
            }
            List<exceptionmappingconfig> exceptionMappings = invocation.getProxy().getConfig().getExceptionMappings();
            String mappedResult = this.findResultFromExceptions(exceptionMappings, e);
            if (mappedResult != null) {
            	
            	// メッセージコードの格納
            	Exception ex = e; 
            	if (isDefaultMessageCode(e)) {
            		ex = new JcSystemException(getDefaultMessageCode());
            	}
            	
                result = mappedResult;
                publishException(invocation, new ExceptionHolder(ex));
            } else {
                throw e;
            }
        }

		return result;
	}

	/**
	 * デフォルトのメッセージコードを適用するかどうか
	 * @param e
	 * @return
	 */
    private boolean isDefaultMessageCode(Exception e) {
    	if (e instanceof JcSystemException) {
			if (StringUtils.isBlank(e.getMessage())) {
				return true;
			}
		} else {
			return true;
		}
    	return false;
	}

	private String findResultFromExceptions(List</exceptionmappingconfig><exceptionmappingconfig> exceptionMappings, Throwable t) {
        String result = null;

        // Check for specific exception mappings.
        if (exceptionMappings != null) {
            int deepest = Integer.MAX_VALUE;
            for (Object exceptionMapping : exceptionMappings) {
                ExceptionMappingConfig exceptionMappingConfig = (ExceptionMappingConfig) exceptionMapping;
                int depth = getDepth(exceptionMappingConfig.getExceptionClassName(), t);
                if (depth >= 0 && depth < deepest) {
                    deepest = depth;
                    result = exceptionMappingConfig.getResult();
                }
            }
        }

        return result;
    }
}
</pre>
<p>■applicationContext.xml</p>
<pre lang="XML" line="1">
	<bean id="jcExceptionInterceptor" class="org.fukata.jc_common.interceptor.JcExceptionInterceptor"
		scope="prototype">
		<property name="defaultMessageCode" value="exception.M00100"></property>
	</bean>
</pre>
<p>■struts.xml</p>
<pre lang="XML" line="1">
		<!-- インターセプター -->
		<interceptors>
			<interceptor name="jcException" class="jcExceptionInterceptor"></interceptor>
			<interceptor name="login" class="loginInterceptor"></interceptor>

			<interceptor -stack name="myDefaultStack">
				<interceptor -ref name="jcException"></interceptor>
				<interceptor -ref name="login"></interceptor>
				<interceptor -ref name="alias"></interceptor>
				<interceptor -ref name="servletConfig"></interceptor>
				<interceptor -ref name="i18n"></interceptor>
				<interceptor -ref name="prepare"></interceptor>
				<interceptor -ref name="chain"></interceptor>
				<interceptor -ref name="debugging"></interceptor>
				<interceptor -ref name="profiling"></interceptor>
				<interceptor -ref name="scopedModelDriven"></interceptor>
				<interceptor -ref name="modelDriven"></interceptor>
				<interceptor -ref name="fileUpload"></interceptor>
				<interceptor -ref name="checkbox"></interceptor>
				<interceptor -ref name="staticParams"></interceptor>
				<interceptor -ref name="actionMappingParams"></interceptor>
				</interceptor><interceptor -ref name="params">
					<param name="excludeParams"/>dojo\..*,^struts\..*
				</interceptor>
				<interceptor -ref name="conversionError"></interceptor>
				<interceptor -ref name="validation">
					<param name="excludeMethods"/>input,back,cancel,browse
				</interceptor>
				<interceptor -ref name="workflow">
					<param name="excludeMethods"/>input,back,cancel,browse
				</interceptor>
			
		</interceptors>

		<default -interceptor-ref name="myDefaultStack"></default>

		<global -results>
			<result name="exception">/jsp/Error.jsp</result>
		</global>

		<global -exception-mappings>
			<exception -mapping result="exception" exception="java.lang.Exception"></exception>
		</global>
</pre>
<p></exceptionmappingconfig></p>
]]></content:encoded>
					
					<wfw:commentRss>/archives/1429/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>[Struts2]validateエラー時のchainについて</title>
		<link>/archives/1413/</link>
					<comments>/archives/1413/#respond</comments>
		
		<dc:creator><![CDATA[fukata]]></dc:creator>
		<pubDate>Mon, 20 Jul 2009 11:58:56 +0000</pubDate>
				<category><![CDATA[開発]]></category>
		<category><![CDATA[struts2]]></category>
		<guid isPermaLink="false">http://fukata.org/?p=1413</guid>

					<description><![CDATA[現在、アプリを作成していて、入力画面→入力エラー→入力画面みたいな遷移で、入力画面には、サイドバーなどに共通項目があるんですが、画像のように、「ArticleCreateAction」で共通項目につい ... <a href="/archives/1413/"> 続きを読む</a>]]></description>
										<content:encoded><![CDATA[<p><a href="https://farm6.static.flickr.com/5134/5476239382_877b048387_m.jpg" target="_blank" title="ValidationErorrSequence"><img loading="lazy" src="https://farm6.static.flickr.com/5134/5476239382_877b048387_m.jpg" alt="ValidationErorrSequence" width="200" height="150" class="attachment wp-att-1414 alignleft" /></a>現在、アプリを作成していて、入力画面→入力エラー→入力画面みたいな遷移で、入力画面には、サイドバーなどに共通項目があるんですが、画像のように、「ArticleCreateAction」で共通項目について取得したいと思ってるんですが、validateメソッドでのエラー時にはどうもchainはされるんですが、executeメソッドは実行されないようです。</p>
<p>今は仕方ないので、「ArticleCreateWithValidationAction」のvalidateメソッド内で共通項目についても取得しているんですよね。。。何かうまい方法はないんでしょうかね。</p>
<p>まぁ、今作っているアプリは確認画面を作成するのに手間がかかるので、javascriptでの確認ウィンドウを出すだけにしているんですけど、実際の業務で作成することになるアプリでは確認画面をどうしても作成することになるからその辺のtipsも集めたいんですけどね。</p>
<p>あと、あれだなぁ、validateについてもxmlで行うか、Action内のvalidateメソッドで行うかも統一した方がいいんだろうなと思う。簡単なvalidateだけならxmlの方が簡単なんですけど、DBが絡んでくるとどうしてもvalidateメソッドで実装した方が簡単に思える。もしかするとカスタムValidate XMLを作成すれば同じように比較的簡単に記述出来るのかもしれないですけど。この辺ももう少し調べたい。</p>
]]></content:encoded>
					
					<wfw:commentRss>/archives/1413/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>[JC]Struts2でjsp内でsessionの値の取得について</title>
		<link>/archives/1392/</link>
					<comments>/archives/1392/#comments</comments>
		
		<dc:creator><![CDATA[fukata]]></dc:creator>
		<pubDate>Mon, 06 Jul 2009 20:43:34 +0000</pubDate>
				<category><![CDATA[開発]]></category>
		<category><![CDATA[JCommunity]]></category>
		<category><![CDATA[jsp]]></category>
		<category><![CDATA[session]]></category>
		<category><![CDATA[struts2]]></category>
		<guid isPermaLink="false">http://fukata.org/?p=1392</guid>

					<description><![CDATA[セッションにキー「user」としてUserクラスのインスタンスを格納して、jsp内で、Userクラスのnameフィールドを表示したい。というようなシナリオがあるとします。今回はそのようなシナリオでやっ ... <a href="/archives/1392/"> 続きを読む</a>]]></description>
										<content:encoded><![CDATA[<p>セッションにキー「user」としてUserクラスのインスタンスを格納して、jsp内で、Userクラスのnameフィールドを表示したい。というようなシナリオがあるとします。今回はそのようなシナリオでやっていこうと思います。</p>
<p>■User.java</p>
<pre lang="JAVA" line="1">
public class User {
	private String name;
	
	public String getName(){
		return this.name;
	}

	public String setName(String name){
		return this.name = name;
	}
}
</pre>
<p>■Hoge.jsp</p>
<pre lang="html" line="1">
Hello <s :property value="#session.user.name"></s>
</pre>
<p>簡単に書きましたが、以下のフォーマットでアクセスできるようです。</p>
<pre lang="html">
<s :property value="#session.[キー名].[フィールド名]"></s>
</pre>
<p>ちなみに、Mapなんかでも同じようにアクセスできるので、試してみて下さい。</p>
]]></content:encoded>
					
					<wfw:commentRss>/archives/1392/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
	</channel>
</rss>
