Category Archive: Seam framework

RESTful веб-сервис в Seam Framework

Seam Framework уже включает в себя реализацию спецификации JAX-RS под названием RESTEasy.
В библиотеках Seam вы можете увидеть три jar-файла, относящихся к RESTEasy:

  • jaxrs-api.jar
  • resteasy-jaxrs.jar
  • jboss-seam-resteasy.jar

Настройка
В вашем проекте найдите и откройте файл components.xml.
К корневому элементу components добавьте следующее пространство имен:

xmlns:resteasy="http://jboss.com/products/seam/resteasy"

Также необходимо добавить объявление префикса:

<resteasy:application resource-path-prefix="/restv1"/>

В нашем случае префикс будет restv1. Префикс обычно используется для версионности.

Вид components.xml после внесения наших изменений:

<?xml version="1.0" encoding="UTF-8"?>
<components xmlns="http://jboss.com/products/seam/components"
            xmlns:core="http://jboss.com/products/seam/core"
            xmlns:drools="http://jboss.com/products/seam/drools"
            xmlns:mail="http://jboss.com/products/seam/mail"
            xmlns:persistence="http://jboss.com/products/seam/persistence"
            xmlns:security="http://jboss.com/products/seam/security"
            xmlns:web="http://jboss.com/products/seam/web"
            ...
            xmlns:resteasy="http://jboss.com/products/seam/resteasy"><!--Добавлено-->
            ....
            <resteasy:application resource-path-prefix="/restv1"/><!--Добавлено-->
</components>

Объявим наш класс, который будет обрабатывать REST-запросы:

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Response;
@Path("/ttt")
public class Test {
    @GET
    public Response echo(){
        String msg = "Hello, World!!!";
        System.out.println(msg);
        return Response.status(200).entity(msg).build();
    }
}

Что делает этот класс? По пути /ttt принимает GET-запрос и выводит сообщение «Hello, World!!!» в лог и возвращает его же в качестве ответа.

Сервис доступен по адресу:
http://<Сервер>:<Порт>/<Имя веб-приложения>/seam/resource/restv1/ttt

Если ввести в браузер этот адрес, то в лог и в браузер будет выведено сообщение: «Hello, World!!!»

Более полную информацию смотрите в документации к Seam Framework: 24.4. RESTful HTTP webservices with RESTEasy

Шаблоны для построения интерфейса на Seam Framework 2.2.0 с использоватеним RichFaces 3.3.3

template.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:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:rich="http://richfaces.org/rich"
      xmlns:a="http://richfaces.org/a4j"
      xmlns:s="http://jboss.com/products/seam/taglib">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <title>#{interface['system.name']}</title>
    <link rel="shortcut icon" href="#{facesContext.externalContext.requestContextPath}/img/favicon.ico" type="image/x-icon"/>
    <link href="#{facesContext.externalContext.requestContextPath}/css/theme.css" rel="stylesheet" type="text/css"/>
    <ui:insert name="scripts"/>
</head>
<body>
 
<noscript style="text-align: center; font-size:9pt; color:red;">
    <div>
        <br/>
        <strong>Для корректной работы необходим браузер с поддержкой JavaScript</strong>
    </div>
</noscript>
 
<TABLE width="100%" cellpadding="0" cellspacing="0">
    <ui:insert name="body"/>
</TABLE>
 
</body>
</html>

Страница, использующая шаблон

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
                xmlns:s="http://jboss.com/products/seam/taglib"
                xmlns:ui="http://java.sun.com/jsf/facelets"
                xmlns:f="http://java.sun.com/jsf/core"
                xmlns:h="http://java.sun.com/jsf/html"
                xmlns:rich="http://richfaces.org/rich"
                xmlns:a="http://richfaces.org/a4j"
                template="../layout/template.xhtml">
    <ui:define name="body">
        <rich:panel>
            <f:facet name="header">#{interface['page.name']}</f:facet>
            <h:messages globalOnly="true" styleClass="message"/>
            <h:form>
 
            </h:form>
        </rich:panel>
    </ui:define>
</ui:composition>

Вывод таблицы

<rich:dataTable id="tableList"
	rowKeyVar="rowIndex" var="req"
	value="#{workManager.foundRequestList}">
 
</rich:dataTable>

Вывод таблицы постранично

<rich:datascroller align="center" for="tableList" maxPages="10"
				   page="#{workManager.dataTableScrollerBean.currentPage}"
				   style="width:100%;" fastStep="5" fastControls="auto"
				   renderIfSinglePage="false">
	<f:facet name="first">
		<h:outputText value="#{interface['first.page']}"/>
	</f:facet>
	<f:facet name="last">
		<h:outputText value="#{interface['last.page']}"/>
	</f:facet>
	<f:facet name="previous">
		<h:outputText value="#{interface['previous.page']}"/>
	</f:facet>
	<f:facet name="next">
		<h:outputText value="#{interface['next.page']}"/>
	</f:facet>
	<f:facet name="fastrewind">
		<h:outputText value="-5"/>
	</f:facet>
	<f:facet name="fastforward">
		<h:outputText value="+5"/>
	</f:facet>
</rich:datascroller>
 
<rich:dataTable id="tableList"
	rowKeyVar="rowIndex" var="req" rows="10"
	value="#{workManager.foundRequestList}">
 
</rich:dataTable>

Вывод сообщения о том, что в таблице нет записей

<s:div rendered="#{empty workManager.foundRequestList}"
	   styleClass="nodata">
	<h:outputText value="#{interface['list.is.empty']}"/>
</s:div>

Два JBoss 4.2.2 на одном сервере

Опишу сначала ситуацию: Два приложения на Seam Framework (два war-ника) нужно было запустить на одном сервере, но т.к. в приложениях многие seam-компоненты, которые были созданы, имели одинаковые имена, был конфликт.
Можно, конечно, добиться уникальности названий компонентов, но это нужно переписать кучу кода и в дальнейшем следить за уникальностью названий в обоих приложениях. Я пошел по этому пути, и приложения запускались и работал без ошибок, но при работе с сервисами возникли проблемы, т.к. jboss путался в компонентах.
Тогда пришло решение запустить приложения на разных jboss’ах.

Запустить два jboss’а на одном сервере относительно просто: нужно добиться того, чтобы jboss’ы не использовали одинаковые порты, а этих портов не мало. И чтобы не путаться в портах, к портам одного их jboss’ов можно добавлять единичку. Это выглядит так: 8009 -> 18009, 1099 -> 11099, 1098 -> 11098 и т.д.
Я делал следующим образом: запускал один jboss, после его полной загрузки запускал второй и смотрел какие порты конфликтуют, заменял эти порты, потом еще раз перезапускал второй jboss до тех пор, пока второй jboss стартовал без конфликтов портов.
Ниже приведу список файлом и замен портов (конфигурация default):


bin\run.bat
8787 -> 18787


server\default\conf\jboss-service.xml
8083 -> 18083
1099 -> 11099
1098 -> 11098
4444 -> 14444
4445 -> 14445
4446 -> 14446


server\default\deploy\ejb3.deployer\META-INF\jboss-service.xml
3873 -> 13873 (этот порт встречается дважды в файле)


server\default\deploy\jboss-web.deployer\server.xml
8080 -> 8085 (порты через, которые будет работать web)
443 -> 1443
5443 -> 15443
8009 -> 18009


server\default\deploy\jms\uil2-service.xml
8093 -> 18093


Также нужно учесть, что теперь debug первого приложения будет по порту 8787, а второго по порту 18787.