Java EE part1

0001nobodyさん2011/03/21(月) 00:15:17.26 ID:???
このスレではJava EE中心の話題を扱います。
GuiceやSpring等のDI関連の話題もOKです。

Java EE at a Glance(OracleのJavaEE公式)
http://www.oracle.com/technetwork/java/javaee/overview/index.html

NetBeans(統合開発環境)
http://netbeans.org/index_ja.html

Eclipse(統合開発環境)
http://www.eclipse.org/

0002 ◆WeIzaoS14noj 2011/03/23(水) 01:41:18.04 ID:???
JavaEE 6でお手軽AjaxChat開発

バージョンアップを重ねる毎にリッチな環境が簡単に作れるようになったJavaEE。
かつては初期の開発難度や肥大化した工数によって敬遠されがちでしたが、今はそうではありません。
最新のJavaEE 6環境で簡単にWebアプリが開発できることを、私が勉強しながらお伝えします。


【0.開発概要】
ログイン画面とチャット画面をもつシンプルなアプリケーションを作成します。
今回の開発ではデータベースにはアクセスしません。
本開発では作業者は主に以下の7ファイルを作成・編集(=コーディング)します。
・ログイン画面(index.xhtml, LoginPage.java)
・チャット画面(chat.xhtml, ChatPage.java)
・その他の管理クラス(User.java, Message.java MessagePool.java, SessionFilter.java)

0003 ◆WeIzaoS14noj 2011/03/23(水) 01:42:15.06 ID:???
【1.開発環境のインストール】
NetBeansのJava開発用(ダウンロードページの左から3つ目)をインストールする
※開発環境はEclipseでもいいけど、以下の説明はNetBeans向けになっています。


【2.まずはプロジェクトの作成】
新規プロジェクト
 →Java EE
  →Web アプリケーション
完了

プロジェクト名に「AjaxChat」
主プロジェクトに設定にチェック
次へ

サーバー「GlassFish Server3」
Java EE バージョン「Java EE 6 Web」
コンテキストパス「/AjaxChat」※
次へ
http://localhost:8080/AjaxChat/がアプリケーションのトップページとなる

フレームワーク「JavaServer Faces」
完了

プロジェクトを右クリック
→実行
(メニューバー、ツールバーの「主プロジェクトを実行」でもよい)

これでHallo Worldレベルですがプロジェクトが作成できました。

0004 ◆WeIzaoS14noj 2011/03/23(水) 01:45:38.62 ID:???
【3.ログイン画面の作成】
・index.html
---------------------------------------------------------------------------
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>AjaxChat ログインページ</title>
</h:head>
<h:body>
<h1>AjaxChat ログインページ</h1>
<h:form id="loginForm" prependId="false">
Room Name: <h:inputText id="roomName" value="#{loginPage.roomName}" validator="#{loginPage.validate}" />
<h:message id="roomNameError" for="roomName" style="color: red"/><br />
User Name: <h:inputText id="userName" value="#{loginPage.userName}" validator="#{loginPage.validate}" />
<h:message id="userNameError" for="userName" style="color: red"/><br />
<h:commandButton id="login" value="Login" action="#{loginPage.login}"/>
</h:form>
</h:body>
</html>
---------------------------------------------------------------------------
見慣れないタグが付けられていますが、各々は基本的にはHTMLのinputタグに変換されます。
HTML式に書くことも可能ですが、その場合は余計なタグをいくつか記述する必要が在るので、
HTMLだけを描くデザイナと仕事をするでもなければ、JSFタグを直接打った方が補完も利き手間要らずです。

0005 ◆WeIzaoS14noj 2011/03/23(水) 01:46:45.43 ID:???
・User.java
→新規
 →その他
  →JavaServer Faces
   →JSF管理対象Bean
    →クラス名「User」
     パッケージ名「ajaxchat」
     スコープ「session」
完了
---------------------------------------------------------------------------
@ManagedBean
@SessionScoped
public class User implements Serializable {
    private String roomName;
    private String userName;
    public String getRoomName() {
        return roomName;
    }
    public void setRoomName(String roomName) {
        this.roomName = roomName;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public boolean isLoginNow() {
        return roomName != null && !roomName.isEmpty()
                && userName != null && !userName.isEmpty();
    }
}

0006 ◆WeIzaoS14noj 2011/03/23(水) 01:48:46.40 ID:???
・LoginPage.java
→新規
 →JSF管理対象Bean
  →クラス名「LoginPage」
   パッケージ名「ajaxchat」
   スコープ「view」
完了
---------------------------------------------------------------------------
@ManagedBean
@ViewScoped
public class LoginPage implements Serializable {
    private String roomName;
    private String userName;
    @ManagedProperty("#{user}")
    private User user;
    public String getRoomName() {
        return roomName;
    }
    public void setRoomName(String roomName) {
        this.roomName = roomName;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }

0007 ◆WeIzaoS14noj 2011/03/23(水) 01:49:59.74 ID:???
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }
    // 入力検査
    public void validate(FacesContext fc, UIComponent component, Object value) {
        String id = component.getId();
        String inputData = (String) value;
        if ("roomName".equals(id)) {
            if (inputData.isEmpty()) {
                throw new ValidatorException(new FacesMessage("ルーム名は必須です。"));
            }
        } else if ("userName".equals(id)) {
            if (inputData.isEmpty()) {
                throw new ValidatorException(new FacesMessage("ユーザ名は必須です。"));
            }
        }
    }
    public String login() {
        user.setRoomName(roomName);
        user.setUserName(userName);
        //?faces-redirect=trueを入れるとブラウザ上でもページが遷移する(リダイレクトだから)
        return "chat?faces-redirect=true";
    }
}

0008 ◆WeIzaoS14noj 2011/03/23(水) 01:51:26.54 ID:???
・chat.html
→新規
 →その他
  →JavaServer Faces
   →JSF ページ
    →ファイル名「chat」
完了
※今回は遷移後の確認画面としてのみ利用。

ここまで出来たら実行して確認。未入力欄があると入力欄横にエラーメッセージ、
入力要件を満たすと次画面に遷移します。
値検査、画面遷移、セッション管理が出来ました。Strutsより簡単です。

0009 ◆WeIzaoS14noj 2011/03/23(水) 01:52:12.41 ID:???
【4.さっそくAjax化しよう】
・index.xhtml
---------------------------------------------------------------------------
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">
    <h:head>
        <title>AjaxChat ログインページ</title>
    </h:head>
    <h:body>
        <h1>AjaxChat ログインページ</h1>
        <h:form id="loginForm" prependId="false">
            Room Name: <h:inputText id="roomName" value="#{loginPage.roomName}" validator="#{loginPage.validate}" />
            <h:message id="roomNameError" for="roomName" style="color: red"/><br />
            User Name: <h:inputText id="userName" value="#{loginPage.userName}" validator="#{loginPage.validate}" />
            <h:message id="userNameError" for="userName" style="color: red"/><br />
            <h:commandButton id="login" value="Login" action="#{loginPage.login}">
                <f:ajax execute="roomName userName" render="roomNameError userNameError"/>
            </h:commandButton>
        </h:form>
    </h:body>
</html>

0010nobodyさん2011/03/23(水) 17:25:45.87 ID:???
http://hibari.2ch.net/test/read.cgi/tech/1295892452/
★★Java質問・相談スレッド143★★
http://hibari.2ch.net/test/read.cgi/tech/1190032149/
***Javaのオススメ入門書*** 『創るJava』 3.0
http://hibari.2ch.net/test/read.cgi/tech/1228452306/
Javaやらないか(超初心者向け)
http://hibari.2ch.net/test/read.cgi/tech/1261232019/
Java低速GUI Swing 9
http://hibari.2ch.net/test/read.cgi/tech/1295886572/
Eclipse統合M31【Java/C++/Ruby/Python/Perl】

http://hibari.2ch.net/test/read.cgi/tech/1217536023/
△△もっとStruts2の良さを教えてくださいSsssion6
http://hibari.2ch.net/test/read.cgi/tech/1132407308/
【Java】Wicket【HTML】
http://hibari.2ch.net/test/read.cgi/tech/1227196176/
【DI】Java Spring Frameworkを語るスレ 4.0
http://hibari.2ch.net/test/read.cgi/tech/1220671877/
Java⇔RDBのMapping-Frameworkを語るスレ Vol.5
http://hibari.2ch.net/test/read.cgi/tech/1067531714/
Tapestryについて語ろうよ!
http://hibari.2ch.net/test/read.cgi/tech/1219242206/
【Java】DIコンテナって本当に便利か?

0011 ◆WeIzaoS14noj 2011/03/23(水) 18:46:44.09 ID:???
>>10
ありがとうございます。私もテンプレ揃えてから始めるべきでした。

0012 ◆WeIzaoS14noj 2011/03/23(水) 18:51:41.77 ID:???
>>4>>9では、ここだけ変わってます。
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"> ←ココ

<h:commandButton id="login" value="Login" action="#{loginPage.login}">
    <f:ajax execute="roomName userName" render="roomNameError userNameError"/> ←ココ
</h:commandButton>

このバージョンでサーバーに配備・実行すると、ログインページは既にAjax化されています。
わざと未入力状態でLoginボタンを何度か押下してみてください。
エラーメッセージは帰りますがブラウザ下部(ステータスバー)のプログレスバーは反応しません。
入力要件を満たしたときのみ画面は遷移します。(Chromeでは違いがわからないかも)

f:ajax要素のexecute属性のroomName userNameはJSFのComponentIDです。
これはHTMLタグ上のidと関連付けられていて、JavaScript側でもそのIDにアクセスできます。
Ajax対応版ではこのIDを持つComponentのみ(ある種の引数として)サーバで解釈され、
その後、エラーが無ければloginPage.loginを実行、正常ならチャット画面へと遷移します。
エラーの場合、render属性に指定したroomNameError userNameErrorのふたつのComponentを再描画します。

これは裏側ではXMLHttpRequestがroomNameとuserNameのidを持つHTMLのinput要素をサーバーに送信し、
レスポンスをごにょごにょし(ぉぃ)、エラーなら*NameErrorに描画、正常なら遷移処理を実行しています。
プログラマはf:ajaxタグに必要最低限の入出力情報を記述するだけですが、これだけのことをしてくれます。

続いてチャット機能を作成します。

0013 ◆WeIzaoS14noj 2011/03/23(水) 19:04:01.35 ID:???
【5.チャット機能を作ろう】
・Massage.java
→新規
 →Java クラス
  →クラス名「Message」
完了
---------------------------------------------------------------------------
public class Message implements Serializable {
    private String userName;
    private String comment;
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public String getComment() {
        return comment;
    }
    public void setComment(String comment) {
        this.comment = comment;
    }
}

0014 ◆WeIzaoS14noj 2011/03/23(水) 19:05:22.82 ID:???
・MessagePool.java
 →JSF管理対象Bean
  →クラス名「MessagePool」
   パッケージ名「ajaxchat」
   スコープ「application」
---------------------------------------------------------------------------
@ManagedBean
@ApplicationScoped
public class MessagePool implements Serializable {
    private static final int maxMessageSize = 15;
    private Map<String, Deque<Message>> pool = new ConcurrentHashMap<String, Deque<Message>>();
    @SuppressWarnings("unchecked")
    public Collection<Message> getMessagesBy(String roomName) {
        Deque<Message> messages = getMessages(roomName);
        Collection<Message> responce;
        synchronized (messages) {
            responce = (Collection<Message>) ((LinkedList<Message>) messages).clone();
        }
        return responce;
    }
    public void addMessage(String roomName, String userName, String comment) {
        Deque<Message> messages = getMessages(roomName);
        Message msg = new Message();
        msg.setUserName(userName);
        msg.setComment(comment);
        synchronized (messages) {
            if (messages.size() >= maxMessageSize) {
                messages.removeLast();
            }
            messages.addFirst(msg);
        }
    }

0015 ◆WeIzaoS14noj 2011/03/23(水) 19:06:38.86 ID:???
    private Deque<Message> getMessages(String roomName) {
        if (roomName == null) {
            throw new NullPointerException("roomName");
        }
        Deque<Message> messages = pool.get(roomName);
        if (messages == null) {
            messages = new LinkedList<Message>();
            pool.put(roomName, messages);
        }
        return messages;
    }
}
---------------------------------------------------------------------------

・ChatPage.java
→新規
 →JSF管理対象Bean
  →クラス名「ChatPage」
   パッケージ名「ajaxchat」
   スコープ「view」
完了
---------------------------------------------------------------------------
@ManagedBean
@ViewScoped
public class ChatPage implements Serializable {
    @ManagedProperty("#{messagePool}")
    MessagePool messagePool;
    @ManagedProperty("#{user}")
    User user;
    private String comment;

0016 ◆WeIzaoS14noj 2011/03/23(水) 19:09:22.67 ID:???
    public MessagePool getMessagePool() { return messagePool; }
    public void setMessagePool(MessagePool messagePool) { this.messagePool = messagePool; }
    public User getUser() { return user; }
    public void setUser(User user) { this.user = user; }
    public String getComment() { return comment; }
    public void setComment(String comment) { this.comment = comment; }
    public void validate(FacesContext fc, UIComponent component, Object value) {
        String inputData = (String) value;
        if (inputData.isEmpty()) {
            return;
        }
        if (inputData.contains("うんこ")) {
            throw new ValidatorException(new FacesMessage("そういうのはあかん"));
        }
    }
    public Collection<Message> getMessages() {
        return messagePool.getMessagesBy(user.getRoomName());
    }
    public void sayMessage() {
        if (comment == null || comment.isEmpty()) {
            return;
        }
        messagePool.addMessage(user.getRoomName(), user.getUserName(), comment);
        comment = null;
    }
}

0017 ◆WeIzaoS14noj 2011/03/23(水) 19:15:35.71 ID:???
・chat.html
---------------------------------------------------------------------------
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>AjaxChat チャットページ</title>
<script type="text/javascript">
var tid = -1;
function doSubmitComment(evt) {
try {
if (!evt) { evt = event; }
var charCode;
if (evt.charCode) { charCode = evt.charCode;
} else if (evt.keyCode) { charCode = evt.keyCode;
} else if (evt.which) { charCode = evt.which;
} else { charCode = 0; }
if (charCode == 13) {
var button = document.getElementById('submitComment');
button.click();
return false;
}
return true;
} catch (e) { return true; }
}

0018 ◆WeIzaoS14noj 2011/03/23(水) 19:17:54.18 ID:???
function poll() {
var button = document.getElementById('pollMessages');
button.click(); }
function runPollingThread() { setInterval('poll()', 5000); }
function stopPollingThread() { if (tid != -1) { clearInterval(tid); } }
</script>
</h:head>
<h:body onload="runPollingThread();" onunload="stopPollingThread();">
<h1>ようこそ #{user.userName} さん</h1>
<h:form id="chatForm" prependId="false">
Comment: <h:inputText id="comment" value="#{chatPage.comment}" validator="#{chatPage.validate}" onkeypress="return doSubmitComment(event)" />
<h:commandButton id="submitComment" value="発言" action="#{chatPage.sayMessage}">
<f:ajax execute="comment" render="comment commentError messages"/>
</h:commandButton>
<h:message id="commentError" for="comment" style="color: red"/><br />
Room: #{user.roomName}<br />
Messages:<br />
<h:dataTable id="messages" var="msg" value="#{chatPage.messages}" border="1">
<h:column>
<f:facet name="header">
<h:outputText value="User"/>
</f:facet>
<h:outputText value="#{msg.userName}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Message"/>
</f:facet>
<h:outputText value="#{msg.comment}"/>
</h:column>
</h:dataTable>

0019 ◆WeIzaoS14noj 2011/03/24(木) 06:48:29.24 ID:???
            <h:commandButton id="pollMessages" style="visibility:hidden">
                <f:ajax render="messages"/>
            </h:commandButton>
        </h:form>
    </h:body>
</html>

無理矢理詰め込んだからソースが汚くなりました・・・

これで昔ながらのpolling式のチャットは完成です。連続投稿規制のため詳細は省略。
以上のサンプルから、JSFは独自に仕込んだJavaScriptとも相性が良いようです。
また<h:commandButton id="pollMessages">のような隠しコマンドは
邪道なやり方ですが、JavaScriptとも連携しやすく便利そうです。
(一応jsf.jsというライブラリを使うことでJavaScriptだけでコマンドは実行できるようです。)

次回はJavaEE6の目玉?であるComet(long polling, AsyncServlet)に対応したいと思います。
ネットでぱっと見た限りではJSFの正規機能としてCometが使えるかは分かりませんでした。
そこでサーバの特定のステータス変化を通知する専用のServletをCometで作り、
そこにXMLHttpRequestでアクセス、通知が返るとchat.htmlのJS関数poll()を呼び出す仕様とします。
上手くできるといいのですが。

0020 ◆WeIzaoS14noj 2011/03/26(土) 23:13:09.26 ID:???
jQueryの$.postとJSFのイベントの制御が上手くできません。
自身のチャットコメント送信後にLong Pollingをする以下のJS関数doWaitMessageが再送されないようです。
JavaEE6は使いやすいのですが、Ajaxの制御は難しいですね。。。

function doWaitMessage() {
    var url = '#{facesContext.externalContext.request.contextPath}/observe'
    var data = {observeId:'ajaxchat.MessagePool.received', roomName:'#{user.roomName}'}
    $.post(url, data, doWaitMessageCB, 'html');
}
function doWaitMessageCB(data, status) {
    if (status == 'success') {
        alert('start refresh')
        //$('#refresh').click();
        jsf.ajax.request('refresh', null, {render:'messages'});
        alert('end refresh')
    } else {
        alert('status: ' + status);
    }
    alert('start clearTimeout')
    clearTimeout(tid);
    alert('end clearTimeout & start setTimeout')
    tid = setTimeout('doWaitMessage()', 0);
    alert('end setTimeout')
}

0021 ◆WeIzaoS14noj 2011/03/26(土) 23:14:42.67 ID:???
@WebServlet(name = "ObserveServlet", urlPatterns = {"/observe"}, asyncSupported = true)
public class ObserveServlet extends HttpServlet {
    @Inject
    private MessagePool messagePool;
    private ScheduledThreadPoolExecutor executor;
    @Override
    public void init() throws ServletException {
        super.init();
        executor = new ScheduledThreadPoolExecutor(50);
    }
    @Override
    public void destroy() {
        super.destroy();
        executor.shutdownNow();
    }
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        Map<String, String[]> parameterMap = request.getParameterMap();
        String observeId = (String) request.getParameter("observeId");
        if (observeId != null) {
            if (observeId.equals("ajaxchat.MessagePool.received")) {
                AsyncContext ac = request.startAsync(request, response);
                executor.execute(new AsyncObserveService(ac, messagePool));
            } else {
                response.sendError(HttpServletResponse.SC_BAD_REQUEST);
            }
        } else {
            response.sendError(HttpServletResponse.SC_BAD_REQUEST);
        }
    }

0022 ◆WeIzaoS14noj 2011/03/26(土) 23:16:18.08 ID:???
private class AsyncObserveService implements Runnable {
private AsyncContext ac;
private MessagePool messagePool;
private volatile boolean wating;
private Date lastMessageTime;
public AsyncObserveService(AsyncContext ac, MessagePool messagePool) {
this.ac = ac;
this.messagePool = messagePool;}
@Override
public void run() {
long oid = System.currentTimeMillis();
System.out.println("Observe start: id=" + oid);
HttpServletRequest req = (HttpServletRequest) ac.getRequest();
HttpServletResponse res = (HttpServletResponse) ac.getResponse();
String roomName = req.getParameter("roomName");
res.setContentType("text/plain; charset=UTF-8");
try {
synchronized (this) {
messagePool.addListener(roomName, new ReceiveListener(this));
this.wating = true;
while (this.wating) { this.wait(); } }
PrintWriter out = res.getWriter();
out.print(lastMessageTime.toString());
out.close();
} catch (Exception ex) {
Logger.getLogger(ObserveServlet.class.getName()).log(Level.SEVERE, null, ex);
throw new RuntimeException(ex);
} finally {
ac.complete();
System.out.println("Observe end: id=" + oid);
} } }

0023 ◆WeIzaoS14noj 2011/03/26(土) 23:17:03.71 ID:???
    private class ReceiveListener implements MessageReceiveListener {
        private AsyncObserveService observer;
        public ReceiveListener(AsyncObserveService observer) {
            this.observer = observer;
        }
        @Override
        public void received(String roomName, Message msg, long timestamp) {
            try {
                synchronized (observer) {
                    observer.lastMessageTime = new Date(timestamp);
                    observer.wating = false;
                    observer.notifyAll();
                }
            } catch (Exception ex) {
                Logger.getLogger(ObserveServlet.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException,
            IOException {
        processRequest(request, response);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException,
            IOException {
        processRequest(request, response);
    }
}

0024 ◆WeIzaoS14noj 2011/03/26(土) 23:21:50.70 ID:???
とまあこんな感じでJavaEE6の紹介を終わります。(失敗してんじゃねーか)
今後はソースコード投稿サイト探して連投せずにコードを晒していきたいと思います。

ということで、皆さんでもっとJavaEEを活用していきましょう・・・orz

0025 ◆WeIzaoS14noj 2011/03/27(日) 15:09:58.07 ID:???
一応ぜんぶのソースコードを晒してみます。
前述のバグは恐らくJavaScript回りだと思います。
ttp://www.geocities.jp/weizaos14noj/

0026nobodyさん2011/04/25(月) 10:19:48.53 ID:???
これがjsfか

0027nobodyさん2011/05/03(火) 19:11:59.64 ID:???
エンタープライズおじゃばじゃば

0028nobodyさん2011/05/11(水) 13:25:59.91 ID:???
値段高いからあんまり実績無いね。

0029nobodyさん2011/05/24(火) 22:18:56.43 ID:???
javaのネットワーク関係の質問って、ここではスレ違いですよね。。。

0030nobodyさん2011/05/28(土) 22:43:45.10 ID:???
プログラムの話なら

http://hibari.2ch.net/test/read.cgi/tech/1086238859/
Java ネットワークプログラミング 【教えて!】

0031nobodyさん2011/11/12(土) 21:34:15.51 ID:???
JSF2.0は結局サンプルからして冗長で簡単とは言えないな。
Springからは人が流れてこないし、LLからくる人はplayにいくだろう。

0032nobodyさん2011/11/27(日) 18:27:46.70 ID:???
エスパー様向け質問になってしまい申し訳ありません。

10端末から無限ループでHTTPリクエストを間髪入れず投げまくって負荷テストをしています。
apache+tomcat6+mysqlで単純なWebアプリ(Struts,Spring使用)なのですが、
freeでメモリを監視しているとusedが徐々に徐々に増えていき、
累計数万アクセスに達した時点でヒープ領域がいっぱいになってしまいます。

これはアプリのどこかでメモリリークしてしまっているということでしょうか?
それとも、激安VPSのか細いリソースのサーバでこんな負荷テストをすれば、
GCが間に合わずにこうなってしまうものでしょうか?

※DBまわりはMySQLのThreads_*を監視しているかんじだと問題なさそうです。
※ActionやDAO等はすべてSingletonです。

以上、情報が少なすぎて申し訳ありませんが、よろしくお願いします。

0033nobodyさん2011/11/27(日) 20:32:45.09 ID:???
HttpSession使ってる?使ってた場合、無効化してる?

0034nobodyさん2011/11/27(日) 23:37:50.73 ID:???
>>33
Sessionは仕様上必須なので使っています。

…あ、なるほど!!
curlコマンドを使用してトップ画面のurlを叩きまくっているのですが、
cookieもurlパラメータも指定していないので、
つまりアクセス毎にセッションが生成されてい…る…?

ありがとうございます、確認してみます!

0035nobodyさん2011/11/28(月) 00:22:39.89 ID:???
wget --save-cookie $COOKIE $URL
でCookieを事前に取得してから無限ループのcurlコマンドで
curl --cookie $COOKIE $URL
とするようテストスクリプトを修正したら解決できました!
ありがとうございました!

エスパーは実在した!!!>>33

0036nobodyさん2011/11/29(火) 08:05:14.09 ID:???
Sessionだけで大きな問題になったってことは
Session設計がかなりでかいんじゃないの?

0037nobodyさん2011/12/14(水) 00:38:43.62 ID:???
WEBアプリの日次集計バッチを実装しています。
SpringBatchとかiBATISとか未経験ですので別の方法で手っ取り早く済まそうとしているのですが、
WEBアプリ自体に処理を載せてバッチ用アクションURLを叩いた契機で実行、
httpリクエストをcronから飛ばす、
という横着なやり方はやはり一般的ではないですかね?

というかいくらお手軽実装優先とはいえ、こんなやり方を提案したら怪訝な目でみられちゃいますか?

0038nobodyさん2011/12/14(水) 10:06:06.63 ID:???
いいんじゃないかな

0039nobodyさん2011/12/15(木) 17:39:28.45 ID:???
セキュリティとか気にしていれば、別にかまわんと思うよ。

Webアプリが外部に公開されていた場合、
URLさえ分かれば誰でもバッチ処理を起動できてしまうので、
その辺は注意が必要な気がする。

0040nobodyさん2011/12/19(月) 03:27:48.99 ID:???
struts(1.3)のFormFileが必須項目じゃなくて任意入力項目について知恵をおくれー!!!
意図しないエラーは極力メッセージ出したいからFileNotFoundExceptionとIOExceptionはエラーメッセージ表示したいからgetFileData()をtry〜catchで括ってるんだけど、
それ以前にそもそもユーザが何か入力したのかどうかの判定はgetFileName()が空文字か1文字以上あるかで判定するしかないの?
サイズだと0byteのファイルもありえることを考慮すると駄目そうな気がする

0041nobodyさん2011/12/19(月) 03:28:36.61 ID:???
うむ、だいぶ日本語が崩壊しておる

0042nobodyさん2011/12/19(月) 09:15:00.89 ID:???
それしかないよ

0043nobodyさん2012/12/16(日) 00:02:04.31 ID:VsYzucID
Tomcatでいいじゃない

0044nobodyさん2013/01/23(水) 18:50:13.69 ID:???
web の画面から日時を指定して、その時間にデータベースのバックアップをしたいんだけどどうするとよい?
sastruts + mysql。
一回だけバックアップして終了。バックアップ予定の取り消しあり。
java から cron つくるとよいのか、java から mysql の create event するのがよいのか。
cron から java を呼ぶとかなら情報でてくるんだけど。
java でサーバを作るのは大袈裟なきがするし。

やったことある人、どうやりましたか?

0045nobodyさん2013/02/02(土) 17:41:01.72 ID:oxaswEEL
もうダメだわw

Twitterサイバーテロ事件の原因は話題のJavaの脆弱性wwwww 今すぐアンインストールしろwwwww
http://engawa.2ch.net/test/read.cgi/poverty/1359787786/

0046nobodyさん2015/12/02(水) 18:43:23.30 ID:VW85teK9
WindowsのサーバにインストールしたTomcatに
NetBeansで作成したwarファイルをデプロイし、
表示を確認したのですが、IPだと表示されるのに、
ホスト名だとDNSエラーが出て表示できません。

でも、TomcatのTOPページは、
ホスト名でアクセスできます。

何か設定が必要なのでしょうか?

JAVA EE 3日目のド素人質問ですみませんが、
よろしくお願いします。

0047462015/12/02(水) 18:45:34.57 ID:???
ここはだいぶ昔から更新されていないので、
別のスレに移動します。

失礼しました。

新着レスの表示
レスを投稿する