Thursday, 27 November 2008

RESUMO CERTIFICAÇÃO SCWCD 1.5

Bom pessoal, fiquei um tempo sem postar, pois estou meio sem tempo, é trabalho, faculdade e mais algums projetos pessoais, e ainda tenho que estudar para a certificação, a qual tive que dar um tempo, espero fazer agora em janeiro, mas enquanto estudava eu fiz um resumo baseado no livro Head First Servlets and JSP: Passing the Sun Certified Web Component Developer Exam (SCWCD), nele coloquei algumas das coisas mais importantes de cada capítulo, e gostaria de compartilhar com vocês, pois acredito que esse tipo de informação deve ser compartilhada, pois ajuada muita gente.. não reparem nos erros de português.. :)



Publiquei este resumo no knol: http://knol.google.com/k/jferson-machado/certificao-scwcd/38iv47s6af8r8/3 , para quem quiser editar e colocar mais informações.


Relmente espero que gostem e que ajude alguem.


Abraço!



1 - Why use Servlets & JSPs

Quando o cliente faz uma requisição, o browser manda um request, o servidor processa, e manda um response com um header para o browser ,o browser usa o header para ajudar a processar a pagina HTML, renderiza e mostra para o cliente a pagina ou o recurso solicitado.

O request pode ser feito de varias maneiras, as duas principais são o POST e o GET,

  • GET – é um request simples. Ex. Um link de uma pagina, o trabalho principal é pegar um recurso e mandar de volta. Limitado pelo quantidade de caracteres que o nacegador aceita na URL.
  • POST - é o mais poderoso tipo de request, pode-se requisitar alguma coisa e ao mesmo tempo mandar um formulario de dados para o servidor.

O usuário clica na pagina, que manda um request para o servidor, o qual procura no DD, gera um response que é mandado para o browser, o browser renderiza para o cliente.

  • HTTP usa um request/response – o cliente faz um HTTP request, e o servidor web devolve um HTTP response o qual o browser sabe como lidar.
  • Um HTTP response inclui um codigo de status, o content-type(MIME type) e o atual conteudo do response(HTML,imagens,etc)
  • Um GET request anexa os dados no final da URL.
  • Um POST request inclui os dados no corpo do request.

2 - Web app architecture

O que o contêiner oferece:

  • Suporte de comunicações - Não é preciso se preocupar com comunicações,não é preciso criar sockets, escutar em uma porta.
  • Gerenciamento do Ciclo de Vida - O container cuida de todo o ciclo de vida da aplicação, desde a vida do servlet até sua morte, deixando o objeto legivel para a garbage colector, para ser coletado quando ela passar.
  • Suporte a MultiThread - O container automaticamente cria uma nova thread a cada novo request recebido pelo servlet
  • Segurança declarativa - O container usa um XML Deployment Descriptor para configurar com segurança, sem necessitar de hard code no codigo do servlet.
  • Suporte a JSP - O container cuida da parte de traduzir o jsp em codigo java.


Como o container trabalha um request:

  • o cliente faz um request;
  • o container cria dois objetos, HttpServletRequest e HttpServletResponse;
  • o container encontra o servlet mapeado no DD, preenche o servlet com o Objeto request e response e cria/aloca uma thread para o request;
  • o container chama o método service() , o qual chama o doGet ou doPost, dependendo do tipo do request;
  • o método gera uma resposta conforme o mime type setado, e envia pelo response(o default é HTML);
  • a thread completa, o container converte o objeto response em um Http response e manda de volta para o cliente, então deleta os objetos request e response.

3 - Mini MVC tutorial

No modelo MVC se divide em três partes, modelo, apresentação e controle.

- A apresentação(view) é a parte onde será exibido os dados, geralmente o jsp;

- O modelo(model) é a regra de negócios do seu código;

- O controle(controller) é o servlet,

O ambiente de desenvolvimento, tem a pasta principal com o nome do projeto, e dentro dele as seguintes pastas:

  • etc - onde fica os arquivos de configuração(web.xml);
  • lib - onde ficam as libs da aplicação;
  • src - onde ficam os fontes;
  • classes - onde ficam as classes;
  • web - onde ficam as paginas jsp.

No ambiente de deploy, deve-se criar uma pasta dentro da webapp do tomcat,esta pasta deverá ser o nome do projeto, na raiz dela devem ser colocados as paginas jsp, e criar uma pasta WEB-INF onde terá o arquivo deployment descriptor(web.xml), e onde terá uma pasta classes, que conterá as classes do programa e a pasta lib que conterá as libs necessarias para a aplicação.

4 - Being a Servlet

Ciclo de vida do Servlet:

  • o container carrega a classe;
  • instancia o servlet;
  • chama o método init() (Somente uma vez);
  • chama o método service() (onde ele passa a maior parte da sua vida);
  • chama o método destroy().


- Cada request roda em uma thread separada.
- O método init() precisa ser completado antes de ser chamado o método service()
- Para se tratar dados de um formulário é usado o método HttpServlet.doPost().
- Para pegar um valor do header, como por exemplo o "User-Agent", é usado: request.getHeader("User-Agent");


- Principais interfaces/classes e seus métodos:

javax.servlet.Servlet (Interface)

  • init(ServletConfig)
  • service(ServletRequest,ServletResponse)
  • destroy()&î


javax.servlet.GenericServlet (Interface)


javax.servlet.http.HttpServlet (Classe)

  • service()
  • doGet()
  • doPost()

javax.servlet.ServletRequest (Interface)

  • getAttribute(String) : Object
  • getParameter(String) : String
  • getParameterNames() : Enumeration


javax.servlet.http.HttpServletRequest (Interface)

  • getCookies() : cookies[]
  • getHeader(String) : String
  • getMethod()
  • getSession() : HttpSession

javax.servlet.ServletResponse (Interface)

  • setContentType(String) : void
  • getOutputStream() : ServletOutputStream
  • getWriter() : PrintWriter


javax.servlet.http.HttpServletResponse (Interface)

  • addCookie(Cookie) : void
  • addHeader(String name, String value) : void


ServletConfig

  • Um objeto ServletConfig para cada servlet
  • Parametros são configurados no DD


ServletContext

  • Um objeto ServletContext por aplicação
  • Usado para acessar parametros da aplicação
  • Seus parametros serão globais para a aplicação


Request

  • Se em um formulário não for especificado o tipo do método, o padrão é get. Se você mandar um request do tipo GET, e no seu servlet não for subscrito o método doGet, então ocorrerá um erro.
  • Para pegar um único parametro no servlet, usa-se request.getParameter(), que retorna uma String, mas se tiver mais de um parametro, usa-se request.getParameterValues(), que retorna um array de Strings.
  • Seu servlet sempre extenderá HttpServlet, do qual sobrescreverá os métodos doPost() ou doGet()
  • javax.servlet.http.HttpServlet extende javax.servlet.GenericServlet
  • javax.servlet.GenericServlet implementa a interfaca javax.servlet.Servlet
  • As classes servlet estão em um dos dois pacotes: javax.servlet ou javax.servlet.http
  • Voce pode sobrescrever o método init(), e você precisa sobrescrever um dos métodos sevices: doGet() ou doPost(), etc.
  • Os métodos doGet() e doPost() tem como parametros HttpServletRequest e HttpServletResponse.
  • O método service determina se doGet() ou doPost() irão rodar baseado no método HTTP do HTTP request.
  • Get é idempotent, equanto Post não é.


Response

  • Na maioria das vezes você usará o response para mandar coisas de volta para o cliente.
  • Os métodos mais comuns no response que você usará são setContentType e getWriter
  • O método que você chama em seu response para pegar um stream binario é o getOutputStream()
  • a diferenca entre o addHeader() e o setHeader() é que o setHeader() irá substituir o valor enquanto o addHeader() irá adicionar mais um valor, se não existir nenhum header com o mesmo nome, então os dois terão a mesma função.
  • para redirecionar uma requisição para uma outra pagina, usa-se o sendRedirect(aStringURL)
  • O RequestDispatcher acontece no servidor enquanto o sendRedirect acontece no cliente.

5 - Being a web app

Principais interfaces e métodos:

javax.servlet.ServletContext

  • getInitParameter(String)
  • getInitParameterNames()
  • getAttribute(String)
  • getAttributeNames()
  • setAttribute(String,Object)
  • removeAttribute(String)
  • getRequestDispatcher(String)

ServletConfig

-um por servlet

No DD:

<servlet>

<init-param>

<param-name>adminEmail</param-name>

<param-value>jef@terra.com</param-value>

</init-param>

</servlet>

No codigo do servlet:

out.println(getServletConfig().getInitParameter("adminEmail"));


ServletContext

- um por aplicação web

No DD:

<web-app ...>
<context-param>
<param-name>foo</param-name>
<param-value>bar</param-value>
</context-param>
<!-- outras coisas incluindo a declaração do servlet -->
</web-app>

No codigo do servlet:

getServletContext().getInitParameter("foo"); ou getServletConfig().getServletContext().getInitParameter("foo");

ou

ServletContext context = getServletContext();

out.println(context.getInitParameter("adminEmail"));


Listeners

Configurando um listner no DD:

<web-app ...>

<listener>

<listener-class>

com.example.MyServletContextListener

</listener-class>

</listener>

</web-app>

Para criar uma classe de listener você precisa implementar um listener, eles são todos interfaces e seus métodos tem como parametros eventos.

Cenário

Interface Listener

Tipo do Evento

você quer saber se um atributo em uma aplicação web foi adicionado, removido ou substituído

javax.servlet.ServletContextAttributeListener
attributeAdded
attributeRemoved
attributeReplaced

ServeletContextAttributeEvent

você quer saber quantos usuarios correntes existem. Em outras palavras, você deseja acompanhar as sessoes ativas.

javax.servlet.http.HttpSessionListener
sessionCreated
sessionDestroyed

HttpSessionEvent

a cada request, você quer logar isso.

javax.servlet.ServletRequestListener
requestInitialized
requestDestroyed

ServletRequestEvent

você quer saber quando um atributo do request foi adicionado, removido ou substituído

javax.servlet.ServletRequestAttributeListener
attributeAdded
attributeRemoved
attributeReplaced

ServletRequestAttributeEvent

você tem um atributo de classe (uma classe para um objeto que sera armazenado como um atributo) e quer que objetos do tipo sejam notificados quando são vinculados ou removidos da sessão

java.servlet.http.HttpSessionBindingListener
valueBound
valueUnbound

HttpSessionBindingEvent

você quer saber quando um atributo da sessão foi adicionado, removido ou substituído

javax.servlet.http.HttpSessionAttributeListener
attributeAdded
attributeRemoved
attributeReplaced

HttpSessionBindingEvent

você quer saber quando um contexto foi criado ou destruído

javax.servlet.ServletContextListener
contextInitialized
contextDestroyed

ServletContextEvent

você tem um atributo de classe, e você quer que objetos desse tipo sejam notificados quando uma sessão da qual eles estão vinculados migra para uma outra JVM

javax.servelet.http.HttpSessionActivationListener
sessionDidActivate
sessionWillPassivate

HttpSessionEvent

O HttpSessionBindingListener é diferente de um HttpSessionAttributeListener, pois ele é um plain old object, ele implementa o listener e seu métodos e não é preciso configurá-lo no DD, isso é feito automaticamente.

Atributos

Parametros

Tipos

Application/context
Request
Session

Application/context init parameters
Request parameters
Servlet init parameters

Métodos set

setAttribute(String name, Object value)

não é possivel setar parametros, eles são configurados no DD.

Tipo de Retorno

Object

String

Métodos get

getAttribute(String name)

getInitParameter(String name)

Existem tres escopos:

  • Context - toda a aplicação pode acessar
  • Session - Acessivel somente para quem acessa um especifico HttpSession
  • Request - Acessivel somente para quem acessa um especifico HttpRequest

javax.servlet.ServletContext (interface)

  • getAttribute(String)
  • setAttribute(String,Object)
  • removeAttribute(String)
  • getAttributeNames()

javax.servlet.ServletRequest (interface)

  • getAttribute(String)
  • setAttribute(String,Object)
  • removeAttribute(String)
  • getAttributeNames()

javax.servlet.http.HttpSession (interface)

  • getAttribute(String)
  • setAttribute(String,Object)
  • removeAttribute(String)
  • getAttributeNames()


- Sincronizar o método service é uma péssima ideia.
Errado:

public synchronized void doGet(HttpServletRequest request, HttpServletResponse response){

response.setContentType(“text/html”);
PrintWriter out = response.getWriter();
out.println(“test context attributes<br>”);

getServletContext().setAttribute(“foo”, “22”);
getServletContext().setAttribute(“bar”, “42”);
out.println(getServletContext().getAttribute(“foo”));
out.println(getServletContext().getAttribute(“bar”));

}

- Deve-se sincronizar o context:

Correto:

public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
response.setContentType(“text/html”);
PrintWriter out = response.getWriter();
out.println(“test context attributes<br>”);
synchronized(getServletContext()) {
getServletContext().setAttribute(“foo”, “22”);
getServletContext().setAttribute(“bar”, “42”);
out.println(getServletContext().getAttribute(“foo”));
out.println(getServletContext().getAttribute(“bar”));
}
}


ou o session:


- Deve-se sincronizar o context:

Correto:

public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
response.setContentType(“text/html”);

PrintWriter out = response.getWriter();

out.println(“test session attributes<br>”);

HttpSession session = request.getSession();

synchronized(session) {

session.setAttribute(“foo”, “22”);

session.setAttribute(“bar”, “42”);

out.println(session.getAttribute(“foo”));

out.println(session.getAttribute(“bar”));

}

}

- Dos três contextos, somente o request é seguro em relação a threads.

- Variáveis locais também são seguras em relação a threads.

- SingleThreadModel é feito para proteger variaveis de instancia (Mas não devera ser usado, foi depreciado)

- Somente atributos Request e variáveis locais são seguros em relação a threads.

RequestDispatcher

O requestDispacher é usado para passar o request e o response para outra pagina, ou para outro classe para que essa possa terminar o trabalho. A sua classe tem somente dois métodos: forward(ServletRequest,ServletResponse) e include(ServletRequest,ServletResponse), mas o forward é de longe o mais usado. O RequestDispatcher pode ser usado de duas formas:

- Pegando um RequestDispatcher de um ServletRequest: RequestDispatcher view = request.getRequestDispatcher("result.jsp");

- Pegando um RequestDispatcher de um ServletContext: RequestDispatcher view = getServletContext().getRequestDispatcher("/result.jsp"); (É preciso usar a barra com o getRequestDispatcher, quando este e pego de um ServletContext)

e para chamar o forward: view.forward(request,response);

- Deve-se ter um cuidado especial para não commitar algo antes de chamar o forward.

Relembrando os listeners:

Attribute listeners

ServletRequestAttributeListener
ServletContextAttributeListener
HttpSessionAttributeListener

Outros Ciclos de vida listeners

ServletRequestListener
ServletContextListener
HttpSessionListener
HttpSessionBindingListener
HttpSessionActivationListener

Métodos em todos atributos listeners(exceto binding listener)

attributeAdded()
attributeRemoved()
attributeReplaced()

Ciclo de vida relacionado a session(exceto atributos relacionados a eventos)

quando a sessão é criada e quando é destruida
sessionCreated()
sessionDestroyed()

Ciclo de vida relacionado a request(exceto atributos relacionados a eventos)

quando o request é inicializado e quando é destruído
requestInitialized()
requestDestroyed()

Ciclo de vida relacionado a servlet contexto(exceto atributos relacionados a eventos)

quando o contexto é inicializado e quando é destruído
contextInitialized()
contextDestroyed()

- Se o seu servlet usa RequestDispatcher, ele nunca poderá mandar o seu próprio response.
- Os três tipos relacionados a servlets que podem armazenar atributos são HttpSession, ServletContext e HttpServletRequest.

6 - Conversational state

Para o container saber de qual sessão se trata, o container pega o ID da Sessão do cliente como parte do response, e o cliente manda de volta com um request. O jeito mais simples de se fazer isso é usando cookies.


Enviando um session cookie no Response:

HttpSession session = request.getSession();


Pegando o session ID do request:

HttpSession session = request.getSession();


Note que o método que envia e que recebe é o mesmo.


Para ver se uma sessão ja existe ou se foi recentemente criada usa-se o método isNew: session.isNew();

Para pegar uma sessão ja existente e sem criar uma nova usa-se: request.getSession(false);


Se o seu navegador não aceitar cookies, voce pode usar o URL rewriting, que adiciona o sessionID no final do url. O método usado para adicionar o SessionID na url: response.encodeURL("/BeerTeste.do")


URL rewriting trabalha com sendRedirect(): response.encodeRedirectURL("/BeerTeste.do");


javax.servlet.http.HttpSession(interface)


o que faz
para que voce usa
getCreationTime()Retorna o tempo em que a sessão foi criada
Para encontrar uma sessão antiga,pode restringir o tempo da sessão. Ex: uma vez logado voce tem 10 min. para preencher o formulario.
getLastAccessedTime()Retorna a ultima vez que o container pegou um request com o este Session ID
Para encontrar quando foi a ultima vez que um cliente acessou esta sessão.
setMaxInactiveInterval()Especifica o tempo máximo em segundos que voce quer habilitar entre um request de um cliente em uma sessão
Para que a sessão seja destruida apos o tempo especificado sem que o cliente tenha feito algum request.
getMaxInactiveInterval()Retorna o tempo maximo em segundos que o cliente esta habilitado entre um request em uma sessão
Para ver quanto tempo a sessão pode estar inativa e continua viva.
invalidate()Termina a sessão. Isto inclui o unbinding de todos os atributos armazenados na sessão corrente.
Para terminar a sessão quando se sabe que ela esta inativa.


Três geitos que a sessão pode morrer:
  • Time out
  • Chamar invalidate()
  • A aplicação cair

Configurando a sessão no DD: (Configurado em minutos)

<web-app ...>
<servlet>
...
</servlet>
<session-config>
<session-timeout>15<session-timeout>
</session-config>
</web-app>


Configurando a sessão para uma sessão específica:


session.setMaxInactiveInterval(20*60); (Configurado em segundos programaticamente)


Setar o session.setMaxInactiveInterval(0) causa um time out imediatamente, mas se voce setar: session.setMaxInactiveInterval(-1) significa que a sessão não irá expirar nunca.


Criando um novo cookie: Cookie cookie = new Cookie("username", "name"). Não existe nenhum método para setar o valor do cookie, por exemplo: cookie.setCookie("username","name") - isto está errado.


Setando quanto tempo o cookie ficará vivo no cliente: cookie.setMaxAge(30*60) (Em segundos)


Mandando um cookie para o cliente: response.addCookie(cookie)


Para pegar um cookie é preciso usar o método getCookies() que retorna um array de cookies, não existe um método que retorne somente um cookie, então para pegar é preciso fazer o seguinte:


Cookie[] cookies = request.getCookies();

for(int i=0;i < cookies.length;i++){

Cookie cookie = cookies[i];

if(cookie.getName().equals("username"){

String userName = cookie.getValue();

out.println("Hello " + userName);

break;

}

}


Percorre todo o array de cookies, e somente para quando achá-lo ou não existir.


Se o cliente não aceitar cookies, uma maneira de gerenciar a sessão seria usando URL rewriter.


Quando for usar cookies para session tracking, o nome do session tracking precisa ser JSESSIONID.


A sessão é criada ou destruida.

Os atributos da sessão podem ser adicionados,substituidos ou removidos.

A sessão é passivated em uma JVM e activated em outra com uma aplicação distribuida.


Para remover atributos da sessão, usa-se session.removeAttribute("nomeDoAtributo"), dado que session é um objeto HttpSession.


Ciclo de vida dos eventos da sessão



Evento
Listener
A sessão foi criada
HttpSessionEventHttpSessionListener
A sessão foi destruida
HttpSessionEventHttpSessionListener
Um atributo foi adicionado
HttpSessionBindingEvent
HttpSessionAttributeListener
Um atributo foi removidoHttpSessionBindingEventHttpSessionAttributeListener
Um atributo foi substituidoHttpSessionBindingEventHttpSessionAttributeListener
A sessão está prestes a ser passivatedHttpSessionEvent
HttpSessionActivationListener
A sessão foi actived
HttpSessionEventHttpSessionActivationListener

Legenda: Ciclo de vida - Atributos - Migração


Na migração o passivated acontece quando o container está prester a migrar a sessão para uma diferente JVM, ele é chamado antes da sessão mudar. Ja o actived acontece quando a migração ja tiver acontecido e é chamado antes de qualquer parte da aplicação possa chamar o getAttribute() na sessão. Para os objetos não se perderem na migração, eles devem ser serializados.


Na migração tudo é duplicado, exceto a HttpSession.


O HttpSessionBindListener não é configurado no DD, ele é implementado por uma old plain java object e é chamado quando a classe é instanciada, então será chamdo o valueBound e valueUnbound.


7 - Being a JSP


Todo jsp é um servlet no final, o container le o arquivo jsp, traduz em uma classe servlet, então compila, é como se voce mesmo tivesse feito

um servlet na mão.


Existem três tipos de diretivas: page, include e taglib.


Scriptlet: <% %>, Directive: <%@ %>,Expression: <%= %>,Declaration: <%! %>,JSP Comment: <%-- --%>


O container gera uma classe do seu jsp e essa classe implementa a interface HttpJspPage. Nessa classe existem três métodos importantes: jspInit(), jspDestroy(),_jspService()


  • jspInit() - Método é chamado do servlet método init(), pode ser sobrescrevido;
  • jspDestroy() - O método é chamado do servlet método destroy(), pode ser sobrescrevido;
  • _jspService() - Este método é chamado do servlet método service(), o qual significa que roda em threads separadas para cada request. O container passa o request e o response para esse método.Voce não pode sobrescrever esse método.
Ciclo de vida do JSP

Voce escreve o .jsp e o container escreve o arquivo .java para o seu jsp.

  1. Voce escreve um arquivo .jsp para usa-lo como parte da aplicação web
  2. O container le o arquivo DD, para esta aplicação, mas não faz nada com o arquivo .jsp
  3. O arquivo .jsp fica esperando por um request do cliente.
  4. O cliente clica em um link no .jsp
  5. O container tenta traduzir o .jsp(MyJsp.jsp) para codigo fonte .java
  6. O container gera o arquivo MyJsp_jsp.java
  7. O container tenta compilar o arquivo MyJsp_jsp.java para gerar o .class(MyJsp_jsp.class)
  8. O container carrega o recem gerado arquivo .class
  9. O container instancia o servlet e faz o método jspInit() rodar
  10. O objeto é agora um verdadeiro sevlet, pronto para aceitar request dos clientes
  11. O container cria uma thread para tratar os requests dos clientes e o servlet método _jspService() roda.
  12. Após isso tudo, é o processo normal de um servlet.
A tradução e compilação acontece somente uma vez no ciclo de vida do JSP.

Configurando servlet init parameters para o JSP:

<web-app ...>
<servlet>
<servlet-name>MyTestInit</servlet-name>
<jsp-file>/TestInit.jsp</jsp-file>
<init-param>
<param-name>email</param-name>
<param-value>jef@terra.com</param-value>
</init-param>
<servlet>
<servlet-mapping>
<servlet-name>MyTestInit</servlet-name>
<url-pattern>TestInif.jsp</url-patter>
</servlet-mapping>
</web-app>




Em um servlet
Em um jsp(usando objetos implicidos)
Application
getServletContext().setAttribute("foo",barObj);
application.setAttribute("foo",barObj);
Request
request.setAttribute("foo",barObj);
request.setAttribute("foo",barObj);
Session
request.getSession.setAttribute("foo",barObj);
session.setAttribute("foo",barObj);
Page
não se aplica
pageContext.setAttribute("foo",barObj);

APIObjectos Implicitos
JspWriter out
HttpServletRequest request
HttpServletResponse response
HttpSession session
ServletContext application
ServletConfig config
Throwable exception
PageContext pageContext
Object page


Atributos de diretiva da pagina:

  • import - Define as declarações de imports java que serão adicionados ao servlet gerado, alguns imports ja vem por default, são eles: java.lang, javax.servlet.http e javax.servlet.jsp.
  • isThreadSafe - Define se os sevlets gerados precisam implementar o SingleThreadModel, não recomendado de se fazer.
  • contentType - Define o MIME type.

  • isELIgnored - Define se expressões EL serão ignoradas quando a pagina for traduzida.

  • isErrorPage - Define se a pagina representa outro JSP de erro. O default é false.

  • errorPage - Define a URL para os recursos ao qual deve ser enviado um erro capturado.

Expression Language (EL)

Isto é EL:
${applicationScope.mail}

O mesmo com expressão JAVA:
<%=application.getAttribute("mail")%>

Para desabilitar todos os scripts existentes nas paginas, e para que os programadores não usem mais scripts, pode-se adicionar ao DD:

<web-app ...>
...
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<scripting-invalid>
true
</scripting-invalid>
</jsp-property-group>
</jsp-config>
...
</web-app>


Isto significa que os scripts estão desabilitados em todos os .jsp


<%@ page isScriptingEnabled=”false” %> - Isto não é mais valido, não esta mais na especificação.


EL é habilitada por default. Se voce quiser desabilitar as EL, coloque no seu DD:


<web-app ...>
...
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<el-ignored>
true
</el-ignored>
</jsp-property-group>
</jsp-config>
...
</web-app>


Pode-se usar também uma diretiva no arquivo .jsp: <%@ page isELIgnored="true"%> . Mas a diretiva feita tem prioridade em relação a feita no DD.




8 - Script-free pages


Standard Actions:
  • <jsp:useBean id="person" class="foo.Person" scope="request" />
jsp:useBean - Identifica a standard action;
id="person" - Declara um identificador para o objeto bean: request.getAttribute("person",p);
class="foo.Person" - Declara o tipo;
scope="request - Identifica o scopo do atributo.
  • <jsp:getProperty name="person" property="name" />
jsp:getpProperty - Identifica a standard action;
name="person" - Identifica o bean atual que fecha com o "id" do <jsp:useBean>
property="name" - Identifica o nome da propriedade, em outras palavras, os atributos da classe que possuem getter e setter da classe.
  • <jsp:setProperty name=”person” property=”name” value=”Fred” />

jsp:setProperty - Identifica a standard action;
name="person" - Identifica o bean atual que fecha com o "id" do <jsp:useBean>
property="name" - Identifica o nome da propriedade, em outras palavras, os atributos da classe que possuem getter e setter da classe.
value="Fred" - É o valor que vai ser setado no bean.

jsp:useBean também pode criar um bean, se ele não existir, então ele irá criar um.


Se o type é usado sem classe, o bean precisa existir.
Se a classe é usada com ou sem type, a classe não precisa ser abstrata e precisa ter um contrutor publico sem argumentos.

<jsp:useBean id=”person” type=”foo.Person” scope=”page”/>

Se não for especificado um escopo em <jsp:useBean> ou <jsp:setBean> o Container irá usar o escopo "page" por default.

type é o que voce DECLARA (pode ser abstrato)
class é o que voce INSTANCIA (precisa ser concreto)
Ex: type x = new class();

Se o nome no input text fechar com o nome do bean, o param não é necessário:
Ex:
<input type=”text” name=”senha”>
<jsp:setProperty name="person" property="senha" />

é o mesmo que:

<input type=”text” name=”userName”>
<jsp:setProperty name="person" property="senha" param="senha" />

Se for usado script para receber o valor, a conversão não funciona:
<jsp:setProperty name=”person” property=”empID” value=”<%= request.getParameter(“empID”)%>”/> - Incorreto, supondo que a propriedade empID é um inteiro, ele vai receber uma String e como está usando script a conversão não irá funcionar.

Expression Language

Se voce quer mostrar um valor da propriedade de uma propriedade, voce deve usar EL(Expression Language):
${person.dog.name}, mostra o name de dog.

Sintaxe:
${primeiraParte.SegundaParte}

A primeiraParte pode ser tanto um Objeto Implicito EL quanto um atributo:


Objeto Implicito EL:

pageScope,requestScope,sessionScope,applicationScope,paramValues,param,header,headerValues,cookie,initParam,pageContext.

Attribute:

pageScope,requestScope,sessionScope,applicationScope.

Exemplo:

${person.name}
  1. person - precisa ser um Map ou um Bean
  2. name - precisa ser uma chave do map ou uma propriedade do bean
  3. name - precisa seguir as regras de nomeação java (letra,_ ou $)
O operador [] da mais opções para você, ele é mais poderoso:
  1. se a expressão tem uma variavel seguida do operador [], as variaveis do lado esquerdo podem ser um Map, um bean, um List ou um array.
  2. se as coisas dentro dos colchetes são um literal String, isto pode ser uma chave de Map ou uma propriedade de um bean ou um index dentro de um List ou array.
Para Maps e javabeans, pode-se usar tanto o ponto quanto os colchetes:
Ex:

Servlet:
java.util.Map musicMap = new java.util.HashMap();
musicMap.put(“Ambient”, “Zero 7”);
musicMap.put(“Surf”, “Tahiti 80”);
request.setAttribute(“musicMap”, musicMap);

jsp:
Music: ${musicMap.Ambient}

ou

Music: ${musicMap["Ambient"]}


Os objetos implicitos da EL:

pageScope;
requestScope; - Um map de atributos do escopo
sessionScope;
applicationScope;

param; - Mapa de do request parameters
paramValues;

header; - Mapas do request headerheaderValues;

cookie; -

initParam; - Um mapa de context init parameters (não servlet parameters)

pageContext; - A unica coisa que não é um Mapa, Este é o real objetivo, uma atual referencia ao pageContext.


Na EL para pegar um parametro de request da pagina pode ser usado:
${param.name} ou se quiser pegar varios valores: ${paramValues.food[0]}

Para pegar o header:
${header.host}
${header["host"]}

Para pegar o metodo do request, não é possível fazer simplesmente um: ${request.method}, nem um ${requestScope.method}, para pegá-lo deve-se pegar um o pageContext que tem um atributo request, e dentro desse request tem o método getMethod:
${pageContext.request.method}

Para pegar um cookie:

${cookie.userName.value}

Para pegar o valor do initParameter:

<context-param>
<param-name>mainEmail</param-name>
<param-value>likewecare@wickedlysmart.com</param-value>
</context-param>

${initParam.mainEmail}

IMPORTANTE: A EL initParam não é para pegar parametros configurados com <init-param>, isso é facil de confundir, a EL initParam é configurado para pegar os parametros do context.

Para chamar um método de uma classe java dentro de um jsp, usa-se a classe que tem o método, um arquivo TLD e um jsp.
  1. Escreva um arquivo java com um método que retorne alguma coisa, para que seja possível exibir o resultado na tela, coloque a classe dentro de /WEB-INF/classes de acordo com o seu pacote.
  2. Escreva uma Tag Library Descriptor (TLD), o qual prove o mapeamento entre a classe JAVA e o jsp. Deste geito o nome do método e o nome da função podem ser diferentes. Coloque o arquivo TLD dentro do diretorio /WEB-INF/.
  3. Coloque a diretiva taglib em seu JSP. Quando quiser usar uma função da TLD, será usado o prefixo com o nome definido na diretiva tablib.
  4. Usar a EL para invocar a função. A parte facil, apenas chamar usando EL: ${prefix:name()}
  • Uma função em um TLD pode conter argumentos, mas deve-se lembrar que dentro do arquivo TLD deve ser especificado o nome totalmente qualificado. ex: java.util.Map
  • O nome do método não precisa fechar com o nome da função, quem diz para o Container qual método chamar é o <function-signature>.
  • Tudo começa com a função <function ...> exeto o nome que é: <name>
Alguns outros operadores EL:

Arithmetic(5)
  • Adição: +
  • Subtração: -
  • Multiplicação: *
  • Divisão: / e div
  • Resto: % e mod
Logical(3)
  • AND: && e and
  • OR: || e or
  • NOT: ! e not
Relational(6)
  • Equals (Igual): == e eq
  • Not Equals: (Diferente) != e ne
  • Less than: (Menor que) < e lt
  • Greater than: (Maior que) > e gt
  • Less than or equals to (Menor ou igual que) <= e le
  • Greater than or equals to (Maior ou igual que) >= e ge

Se for dividido por zero em uma EL voce recebera infinito ao invez de um erro. Mas se voce usar o operador resto com zero, voce irá pegar uma exception

Os valores null na EL, são tratados da seguinte forma:
  • Quando não é encontrado nenhum valor, então não é impresso nada;
  • Para expressões aritméticas são tratados como zero;
  • Para expressões lógicas são tratados como false.
A diretiva include <%@ include %> insere o codigo do "header.jsp", em tempo de tradução. Mas a standard action <jsp:include /> insere o response do "header.jsp", em tempo de execução.

Usar a diretiva include é mais performática que usar a standard action, porque ele é traduzido uma única vez e depois usado.

A diretiva include no primeiro request:
  1. O cliente faz um request para contact.jsp, o qual ainda não foi traduzido. O container le o contact.jsp e inicia o processo de tradução.
  2. O container ve a diretiva include, e combina o codigo do header.jsp e contact.jsp e cria/traduz isto em codigo java para o servlet gerado.
  3. O container compila o codigo traduzido em uma classe servlet. É como qualquer servlet nesse momento e os passos anteriores não acontecerão mais, a não ser que o "header.jsp" mude.
  4. Para completar o request, o container carrega a nova classe compilada, inicializa o servlet(instanciando o servlet chamando init() no novo objeto), alocando um thread para o request, e chamando o método _jspService(). No segundo request o Container irá somente chamar o método service(), alocando um thread e chamando o método _jspService().
A standard action <jsp:include/> no primeiro request
  1. O cliente faz um request para contact.jsp, o qual ainda não foi traduzido. O container le o contact.jsp e inicia o processo de tradução.
  2. O Container ve o include standard action e usa isto para inserir um método chamado no codigo do servlet gerado - que - em tempo de execução - irá dinamicamente combinar o response do header.jsp para o response do contact.jsp. O Container gera servlet para ambos os arquivos JSP.
  3. O Container compila e traduz o arquivo fonte em uma classe servlet. Isto como qualquer outro servlet neste ponto. A classe servlet gerada é carregado pelo Container e é inicializada. Depois o container aloca uma thread para o request e chama o método JSP's _jspService()
  4. O servlet Contact chama o método que faz o include dinâmico, e alguma coisa especifica do vendedor acontece. Todos nos preocupamos sobre o que o response gerado pelo servlet Header é combinado com o response do servlet Contact.
Os nomes dos atributos são diferentes para include directive e <jsp:include/>:

<%@ include file="header.jsp" %>
<jsp:include page="header.jsp" />


9 - Custom tags are powerful


Para usar JSTL é preciso adicionar duas libs na sua aplicação: jstl.jar e standard.jar

Usando c:out, previne cross-site hacking. E quando o valor for null, ele colocará o valor padrão que voce definiu no atributo default do c:out. Ex: Hello <c:out value='${user}' default='guest' /> ou Hello <c:out value=’${user}’>guest</c:out>

O atributo var da tag c:forEach é usado somente dentro do escopo do forEach.

A tag c:if não tem else. Para suprir isso existe a tag c:choose, onde pode ser feitos varias comparações com c:when e se nenhum deles forem verdadeiros, pode-se definir a tag c:outherwise, que é a tag default, então o que tem dentro dela será exibido.

A tag <jsp:setProperty> pode somente fazer uma coisa, setar propriedades nos beans. Para fazer mais que isso existe a tag c:set, que existe em dois tipos:
  • var - usado para setar variaveis de atributos
  • target - usado para setar propriedades de beans ou valores de Mapas.
Cada um dos dois vem em duas variações: com corpo e sem corpo.
  • Não pode se ter os dois: var e target ao mesmo tempo
  • O escope é opcional, se não for setado nenhum o default é page
  • Se o valor for null, o atributo chamado "var" será removido
  • Se o atributo chamado "var" não existir ele será criado, mas somente se o value não for null
  • Se a expressão target for nulla, o Container lancerá uma exceção
  • O "target" é para colocar uma expressão que resolva um Objeto Real, se for colocado uma String literal representando o nome "id" do bean or Map, não funcionará. Em outras palavras target não é para o nome do atributo do beam ou Map - é para o objeto real.
  • Se a expressão "target" não é um Map ou um bean, o Container lancerá uma exceção.
  • Se o "target" for um bean, mas o bean não ter uma propriedade que feche com "property", o Container lancerá uma exceção. Lembre-se que EL ${bean.NotAProperty} também lancará exceção.
Na tag c:remove, se não for especificado um escopo, será removido de todos os escopos.

Diferentes tipos de imports:
  1. A diretiva include: <%@import file="Header.jsp" %>, Translation time
  2. O <jsp:include> standard action: <jsp:include page="Header.jsp"/>, request time
  3. A <c:import> JSTL tag: <c:import url="http://www.terra.com.br/esportes.html"/>, request time
o import <c:import> é o mais poderoso, podendo ir para fora do Container, enquanto os outros dois tipos não podem.

Para definir uma página de erro, defina as tags de error no seu DD, e crie um jsp onde defina a tag isErrorPage="true". Os erros podem ser definidos por codigo ou por tipo de erros, para tratar os erros voce pode definir blocos tipo try/catch com jstl: <c:catch>. Dentro do <c:catch> quando ocorre uma exceção ela é definida para a variavel 'var' se existir, e depois pula para fora do corpo do <c:catch>

Deve-se lembrar que somente as paginas definadas com a tag isErrorPage="true" tem acesso ao real objeto da exceção.

Com functions EL, voce cria a classe Java com o método estatico, chamando o método como voce quiser, então usa o TLD para mapear o método atual<function-signature> para o function<name>. Mas com custon tags, o nome do método é sempre doTag(), entao voce nunca declara o nome do método para uma custon tag. Somente functions usam a assinatura do método declarado no TLD.

Se o <rtextrvalue> não for definido ou se for false, então voce só poderá usar Strings literais e não valores dinâmicos.

Quando a tag <body-content> em uma taglib estiver setada como empty, o único geito de se colocar alguma coisa dentro é com <jsp:attribute>

Antes do JSP 2.0, o desenvolvedor tinha que especificar o mapeamento entre o <uri> no TLD e a atual localização do arquivo TLD. O DD tinha que falar para o Container onde o arquivo TLD com a certa <uri> se encontrava. Mesmo agora depois do JSP 2.0, voce pode espeficicar no DD a tag <taglib>, então quando o Container iniciar, ele irá procurar primeiro no DD e se tiver uma tag <taglib> ele usará para ajudá-lo na busca. Os lugares onde o Container procura pelos arquivos TLD´s são:
  1. Dentro do WEB-INF
  2. Subdiretorios dentro do WEB-INF
  3. Dentro do diretório META-INF, que deve estar dentro de um arquivo jar dentro da pasta WEB-INF/lib
  4. Dentro de um subdiretório do META-INF, que deve estar dentro de um arquivo jar dentro da pasta WEB-INF/lib
As taglib uri precisam ser únicas.

Não se deve usar os prefixos que são reservados, eles são:
  • jsp
  • jspx
  • java
  • javax
  • servlet
  • sun
  • sunw

10 - When even JSTL isn’t enough...


Tag Files - São parecidos com include, só que são melhores. Os arquivos devem ter a extensão .tag, ex: Header.tag. Para chamá-los no jsp deve-se usar a seguinte diretiva: <%@ taglib prefix="myTag" tagdir="/WEB-INF/tags" %> e chamá-los assim: <myTag:Header />, onde Header é o nome do arquivo .tag. Para declarar atributos na tag, existe um tipo de diretiva: <%@ attribute name="subTitle" required="true" rtexprvalue="true" %>, onde required diz que o atributo não é opcional e o rtexprvalue significa que pode ser uma string literal ou uma expressão. Se não for passado nenhum parametro para o atributo e ele for obrigatório, então irá gerar uma exception.

O Container procura pelos arquivos .tag nos seguintes diretorios:
  1. Diretamente dentro do WEB-INF/tags
  2. Dentro de um subdiretorio do WEB-INF/tags
  3. Dentro do diretorio META-INF/tags que está dentro de um arquivo JAR que esta dentro do WEB-INF/lib
  4. Dentro de um subdiretorio do META-INF/tags que está dentro de um arquivo JAR que esta dentro do WEB-INF/lib
  5. Se um arquivo tag é deployado em um JAR, precisa existir um TLD para o arquivo tag.
Um arquivo .tag usa o JspContext ao inves do ServletContext.

Voce pode usar scripts dentro de um arquivo .tag, o que não é possível é usar scripts dentro do corpo do tag usado para invocar um arquivo .tag.

Se for feito deploy de um arquivo .tag em um JAR, precisa ter um arquivo TLD que descreva sua localização. Mas isso não descreve os atributos, body-content, etc. A entrada TLD para um arquivo .tag descreve somente a localização do atual arquivo .tag:

<taglib ....>
<tlib-version>1.0</tlib-version>
<uri>myTagLibrary</uri>
<tag-file>
<name>Header</name>
<path>/META-INF/tags/Header.tag</path>
</tag-file>
</taglib>

Quando arquivos .tag não são o bastante, é usado tag handler. Tag handler que é parecido com EL function, exceto que ..
  • Tag files implementam uma funcionalidade tag usando uma pagina(usando JSP)
  • Tag handler implementa uma funcionalidade tag usando com uma classe JAVA taghandler.
  • Tag handler vem em dois sabores: simple e classic.
  • Para fazer uma simple tag handler, extenda SimpleTagHandler(a qual extends SimpleTag).
  • Para fazer deploy de uma SimpleTagHandler, é preciso criar um TLD que descreva a tag usando o mesmo elemento <tag> usado pela JSTL e outras bibliotecas tag customizadas.
  • Para usar uma Simple tag com um corpo, tenha certeza que a <tag> TLD para esta tag não declare <body-content> empty. Então chame getJspBody().invoke() para o corpo ser processado.
  • A classe SimpleTagSupport inclui implementação para todos os métodos da interface SimpleTag, mais três métodos convenientes incluindo getJspBody(), o qual voce pode usar para acessar o conteudo do corpo da tag.
  • O método setJspBody() será invocado somente se a tag é chamada com um corpo. Se a tag é invocada sem um corpo, como uma tag vazia: <my:tag/> ou nada entre os abre e fecha tags: <my:tag></my:tag>, o método setJspBody() não irá ser chamado. Lembre-se, se a tag tem um corpo, o TLD precisa refletir isso, e o <body-content> não pode ter um valor "empty".
  • A Simple tag's doTag() pode setar um atributo usado pelo corpo da tag, chamando getJspContext().setAttribute() seguido pelo getJspBody().invoke().
  • O método doTag() declara uma JspException e um IOException, então voce pode escrever um JspWriter sem encapsula-lo em um try/catch.
  • Se a tag ter um atributo, declare o atributo no TLD usando o elemento <attribute>, e crie um método setter na classe tag handler, o método setter será chamado antes do doTag().
  • O método getJspBody() retorna um jspFragment, o qual tem dois métodos: invoke(java.io.Writer) e getJspContext() que retorna um JspContext que a tag handler pode usar para acessar o PageContext API(que da acesso a variaveis implicitas e atributos de escopo).
  • Passando null para o invoke() escreva um corpo disponivel para a saida do response, mas voce pode passar outro Writer se voce quer acesso direto ao body content.
  • Declarar uma SkipPageException se voce quiser que a pagina corrente pare o processamento. Se a pagina invocar uma tag que incluiu de outra pagina, o pagina incluida mantem o processamento mesmo que a outra pagina tenha parado o seu processamento.

DynamicAttributes:
  • A interface DynamicAttributes habilita a classe tag handler para aceitar qualquer numeros de atributos de tag.
  • A declaração da tag no TLD precisa incluir o elemento <dynamic-attributes>
  • Atributos explicitos da tag precisam ter um método seter.
  • Tipicamente, voce irá usar um hashmap para armazenar os atributos dinamicos name/value usando o método setDynamicAttribute().
  • Tag Files também pode usar dynamic attributes.
  • Use o atributo dynamic-attributes da tag diretiva.
  • O valor do dynamic-attributes segura um hashmap dos atributos dinamicos.
  • Tipicamente, voce irá usar JSTL forEach para iterar sobre o map.


BodyTagSupport
TagSupport
doStartTag()
posiveis valores de retorno
SKIP_BODY
EVAL_BODY_INCLUDE
EVAL_BODY_BUFFERED
SKIP_BODY
EVAL_BODY_INCLUDE
Valor de retorno default da classe de implementação
EVAL_BODY_BUFFERED
SKIP_BODY
Numero de vezes que pode ser chamado()
Somente uma vez
Somente uma vez
doAfterBody()
posiveis valores de retorno
SKIP_BODY
EVAL_BODY_AGAIN
SKIP_BODY
EVAL_BODY_AGAIN
Valor de retorno default da classe de implementação
SKIP_BODY
SKIP_BODY
Numero de vezes que pode ser chamado()Zero ou muitas
Zero ou muitas
doEndTag()
posiveis valores de retorno
SKIP_PAGE
EVAL_PAGE
SKIP_PAGE
EVAL_PAGE
Valor de retorno default da classe de implementaçãoEVAL_PAGEEVAL_PAGE
Numero de vezes que pode ser chamado()Somente uma vezSomente uma vez
doInitBody() e setBodyContent()
Circunstancias sobre o qual ele pode ser chamado, e numero de vezes de invocação por tag.
Exatamente uma vez, e somente se doStartTag() retornar EVAL_BODY_BUFFERED
Nunca

Usando o método getParent(), uma Classic tag pode acessar uma Classic tag parent, e uma Simple tag pode acessar tanto a Classic ou a Simple parent.


Simple tags
Classic tags
Tag interfaces
SimpleTag(extends JspTag)
Tag(extends JspTag)
IterationTag(extends Tag)
BodyTag(extends IterationTag)
Support implementation classes
SimpleTagSupport(implementa SimpleTag)
TagSupport(implementa IterationTag)
BodyTagSuport(extende TagSupport, implementa BodyTag)
Métodos chaves do ciclo de vida que voce pode implementar
doTag()
doStartTag()
doEndTag()
doAfterBody()
(e para BodyTag - doInitBody() e setBodyContent()
Como voce pode escrever um response output
getJspContext().getOut().println
(não é preciso try/catch pois o método da SimpleTag declara IOException )
pageContext().getOut().println (dentro de um bloco try/catch, pois o os métodos da Classic tag não declaram IOException)
Como acessar variaveis implicitas e atributos de escopo de uma implementacao de suport
Com o método getJspContext(), que retorna um JspContext (o qual geralmente é um PageContext)
Com a variavel implicita pageContext - não é um método parecido com a SimpleTag
Como voce faz o corpo ser processado
getJspBody().invoke(null)
Retornando EVAL_BODY_INCLUDE do doStartTag(), ou EVAL_BODY_BUFFERED se a classe implementar BodyTag.
Como voce causa a parada da pagina atual
Declarando um SkipPageException
Retornando um SKIP_PAGE do doEndTag()



11 - Deploying your web app


A única coisa que muda quando a aplicação web é colocada em um .war, é que o .war vai ter um diretório META-INF, no mesmo nivel da pasta WEB-INF, o resto não muda, fica igual na aplicação web e no arquivo .war.


A única coisa nova que voce verá em uma aplicação web deploiada como um war, é o diretório META-INF(e o arquivo MANIFEST.MF dentro). Você dificilmente irá mexer nesse diretório, a não ser que deseja especificar suas libs dentro do arquivo MANIFEST.MF.


Colocando conteudos dentro do diretório WEB-INF e META-INF, voce estará protegendo o conteudo de acesso direto, como seria se deixa-se ele acessível fora desses diretórios.


O Container irá sempre procurar no WEB-INF/classes antes de procurar dentro do arquivo JAR em WEB-INF/lib.


Se o request bater com mais de um diretório <url-pattern>, então ele pegará o mais especifico, onde /foo/bar/myStuff.do e /foo/bar/*, a primeira opção será escolhida.


O <welcome-file> não começa com uma "/", não confunda isso com os <url-patter>.




Normal JSP page syntaxJSP document syntax
Directives(exceto taglib)<%@ page import="java.util.*" %>
<jsp:directive.page import="java.util.*" />
Declaration<%! int y = 3; %>
<jsp:declaration>
int y = 3;
</jsp:declaration>
Scriptlet<% list.add("Fred"); %>
<jsp:scriptlet>
list.add("Fred");
</jsp:scriptlet>

TextThere is no spoon
<jsp:text>
There is no spoon
</jsp:text>
Scripting Expression<%= it.next() %>
<jsp:expression>
it.next()
</jsp:expression>


-Cuidado, para tag's locais e remotas de ejb são inconsistentes, para local: <ejb-local-ref> e para remoto: <ejb-ref>, no remoto não é usado <ejb-remote-ref>, isso é errado, o mesmo é dito para <local-home> onde para remoto é somente <home> e não <remote-home>



12 - Keep it secret, keep it safe


A <security-constraint> regras para elemento <web-resource-collection>:

  • O elemento <web-resource-collection> tem dois sub-elementos primarios: <url-pattern> e <http-method>
  • O URL pattern e HTTP Methods juntos, definem recursos de request que são condicionados para ser acessados somente pelas regras definidas em <auth-constraint>
  • Um <web-resource-name> é obrigatório
  • Um elemento <description> é opcional
  • Voce precisa especificar pelo menos um <url-pattern>, mas pode ter varios também.
  • Os métodos validos para <http-method> são: GET,POST,HEAD,PUT,TRACE,DELETE e OPTIONS.
  • Voce pode ter mais de um elemento <web-resource-collection> no mesmo <security-constraint>
  • O elemento <auth-constraint> é aplicado para todos elementos <web-resource-collection> em uma <security-constraint>
Regras <role-name>:
  • Dentro de um elemento <auth-constraint>, o elemento <role-name> é opcional.
  • Se um elemento <role-name> existe, ele fala para o Container quais regras estão habilitadas.
  • Se um elemento <auth-constraint> existe com nenhum elemento <role-name>, então nenhum usuario está habilitado.
  • Se <role-name>*</role-name>, então todos usuarios estão habilitados.
  • Role names são case-sentitive.
Regras <auth-constraint>:
  • Dentro de um elemento <security-constraint>, o elemento <auth-constraint> é opcional.
  • Se um <auth-constraint> existe, o Container deve executar a autenticação de URLs associadas.
  • Se um <auth-constraint> não existe, o Container deve permitir acesso a esta URL
  • Para uma melhor leitura, voce pode adicionar <description> dentro <auth-constraint>
Se existir mais de uma tag <security-constraint> que contenha o mesmo diretório, então existe algumas regras que o container usa para distinguir as prioridades:
  1. Quando for uma conbinação individual dos nomes das regras, todas os nomes de regras listados serão habilitados.
  2. Uma regra "*" combinada com alguma coisa mais, da acesso a tudo.
  3. Uma tag <auth-constraint> vazia combinada com alguma coisa mais, nega acesso a tudo. Em outras palavras, uma tag <auth-constraint> vazia é sempre a palavra final.
  4. Se um elemento <security-constraint> não tiver elementos, isto combinado com alguma coisa, dá acesso a todos.
Exemplo de um web.xml com regras definidas:

<web-app>

<security-constraint>

<web-resource-collection>
<web-resource-name>UpdateRecipes</web-resource-name>
<url-pattern>/Beer/AddRecipe/*</url-pattern>
<url-pattern>/Beer/ReviewRecipe/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>

< auth-constraint>
<role-name>Admin</role-name>
<role-name>Member</role-name>
</auth-constraint>

<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>

</security-constraint>

<login-config>
<auth-method>FORM</auth-method>
<form-login-config>
<form-login-page>/loginPage.html</form-login-page>
<form-error-page>/loginError.html</form-error-page>
</form-login-confi g>
</login-config>

</web-app>

Tipos de Autenticação

Tipos
Especificação
Integridade dos dados
Comentarios
BASIC
HTTP
Base64 - fraco
Padrão HTTP, todos os browser suportam isto.
DIGEST
HTTP
Forte - mas não SSL
Opcional para HTTP e Containers J2EE
FORM
J2EE
Muito fraco, sem criptografia
Habilita uma tela de login customizada
CLIENT-CERT
J2EE
Forte, chave publica,(PKC)
Forte, mas os usuários precisam ter certificados.

Para implementar a confidencialidade dos dados e a integridade modernamente e declarativamente é usado dentro do <security-constraint> o elemento <user-data-constraint>. Somente deve existir um <user-data-constraint> por <security-constraint>
Os valores usados dentro do <user-data-constraint> são NONE, INTEGRAL E CONFIDENTIAL, onde:
  • NONE - Este é o default, e isto significa que não existe proteção nos dados.
  • INTEGRAL - Os dados não podem ser mudados ao longo do caminho
  • CONFIDENTIAL - Os dados não podem ser mudados ao longo do caminho
*NOTE: Embora não garantido pela especificação, em prática, todos os Container usam SSL para garantir o transporte, o que significa que ambos INTEGRAL e CONFIDENTIAL funcionam da mesma forma - cada um da a você ambos confidencialidade e integridade. Algumas pessoas recomendam que voce use CONFIDENTIAL, mas novamente, isto nunca irá ser usado, a menos que voce mova para um novo Container que não use SSL.

Diferente do redirect, onde o container diz: "Ei browser, vá a uma URL diferente", com transporte de segurança é um pouco diferente, ao invés de falar para o browser: "vá para uma URL diferente", o Container diz: "Redirecione para o mesmo recurso, mas com um protocolo diferente - use HTTPS ao invés de HTTP".

Autorização opera independente da camada de transporte


13 - The power of filters


Os filters também tem seu ciclo de vida, eles tem métodos init() e destroy() e similiar aos métodos servlets doGet e doPost, filters tem o método doFilter(). Uma aplicação web pode ter muitos filters e eles são declarados no DD.


Todos filters precisam implementar os três métodos da interface Filter: init(), doFilter() e destroy().


No método doFilter() é feito o trabalho pesado, ele recebe três argumentos:

  1. Um ServletRequest(não um HttpServletRequest)
  2. Um ServletResponse(não um HttpServletResponse)
  3. Um FilterChain
Declarando um filter:
<filter>
<filter-name>BeerRequest</filter-name>
<filter-class>com.example.web.BeerRequestFilter</filter-class>
<init-param>
<param-name>LogFileName</param-name>
<param-value>UserLog.txt</param-value>
</init-param>
</filter>

Algumas regras:
  • O <filter-name> é obrigatório
  • O <filter-class> é obrigatório
  • O <init-param> é opcional, e voce pode ter quantos quiser.
Declarando um filter-mapping para um URL pattern
<filter-mapping>
<filter-name>BeerRequest</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>

Algumas regras:
  • O <filter-name> é obrigatório e isto é usado para lincar o elemento <filter> correto
  • Tanto o <filter-name> quanto o <url-pattern> são obrigatórios.
  • O elemento <url-patter> define qual recurso da aplicação web este filtro irá usar.
Declarando um filter-mapping para um servlet
<filter-mapping>
<filter-name>BeerRequest</filter-name>
<servlet-name>AdviceServlet</servlet-name>
</filter-mapping>

Declarando um filter-mapping para um request-dispatcher web resource
<filter-mapping>
<filter-name>MonitorFilter</filter-name>
<url-pattern>*.do</url-pattern>
<dispatcher>REQUEST</dispatcher>
AND/OR
<dispatcher>INCLUDE</dispatcher>
AND/OR
<dispatcher>FORWARD</dispatcher>
AND/OR
<dispatcher>ERROR</dispatcher>
</filter-mapping>

Algumas regras:
  • O <filter-name> é obrigatório
  • Tanto o <filter-name> quanto o <url-pattern> são obrigatórios.
  • Voce pode ter de 0 a 4 elementos <dispatcher>
  • Um elemento REQUEST ativa o filtro para os requests dos clientes. Se nenhum elemento é presente, REQUEST é o default.
  • Um valor INCLUDE ativa o filtro para request dispatching de uma chamada include()
  • Um valor FORWARD ativa o filtro para request dispatching de uma chamada forward()
  • Um valor ERROR ativa o filtro para um recurso chamado pelo error handler.
Os response filter, são um pouco mais complicados, mas podem ser extremamente úteis. Eles lhe dão alguma coisa da saida do response, após o servlet fazer as coisas, mas antes do response ser enviado para o cliente.


14 - Enterprise design patterns


Business Delegate


Usa-se o padrão Business delegate para proteger sua camada web de controle do fato que alguns de seus componentes de modelo do aplicativo são remoto.


Caracteristicas Business Delegate:

  • Atua como um proxy, implementando um remote service's interface
  • Inicializa comunicação com um remote service.
  • Trata detalhes da comunicação e exceções.
  • Recebe request de um componente de controle.
  • Traduz um request e forward para o business service.(via stub).
  • Traduz o response e retorna ele para o controller component.
  • Tratando os detalhes do remote component lookup e comunicações, habilita controller para serem mais coesivos.
Princípios Business Delegate:
  • O Busines delegate é baseado em:
- esconder a complexidade
- codificação de interfaces
- baixo acoplamento
- separação de preocupações
  • Minimiza o impacto da camada de web com as mudanças ocorridas na camada de negócio.
  • Reduz o acoplamento entre as camadas
  • Acrescenta uma camada para o aplicativo, o qual incrementa a complexidade.
  • Metodos chamam a Business Delegate deveria ser "coarse-grained" para reduzir o tráfego de rede

Service Locator

Usa-se o padrão Service Locator para registrar lookup para que voce possa simplificar todos os outros componentes(como Business Delegate) que tem que fazer JNDI(ou outros tipos de registros) lookups.

Caracteristicas Service Locator:
  • Obtem objeto InitialContext.
  • Registro realiza lookup.
  • Trata detalhes da comunicação e exceções.
  • Pode aumentar a performance cacheando referencias obtidas anteriormente.
  • Trabalha com uma variedade de registros, como: JNDI, RMI, UDDI e COS naming.
Princípios Service Locator
  • O Service locator é baseado em:
- esconder a complexidade.
- separação de preocupações.
  • Minimiza o impacto da camada web quando componentes remotos mudam suas localizações e containers.
  • Reduz o acoplamento entre as camadas.

Transfer Object

Usa-se o padrão Transfer object para minimizar o tráfico de rede fornecendo uma representação local de um "fine-grained" componente remoto(geralmente uma entity)

Funções Transfer Object
  • Fornece uma representação de uma entity remota.
  • Minimiza o tráfico de rede.
  • Pode seguir convenções java bean, e com isso pode ser facilmente acessado por outros objetos.
  • Implementa um objeto serializado, e com isso pode se mover entre a rede.
  • Tipicamente facil de ser acessados pelos componentes de apresentação.

Princípios Transfer Object
  • O Transfer object é baseado em:
- redução de tráfico de rede.
  • Minimiza o impacto de performa na camada web quando dados de componentes remotos são acessados com chamadas fine-grained.
  • Reduz o acoplamento entre as camadas.
  • A desvantagem é que os componentes acessando pelo Transfer Object podem receber dados desatualizados, porque os dados do objeto Transfer estão realmente representado o estado em que é armazenada em algum outro lugar.
  • Tornar a atualização de Transfer Objects são concurrency-safe, geralmente é complexa.
Intercepting Filter

Usa-se o padrão Intercepting Filter para modificar request antes de ser enviado para o servlet, ou para modificar response antes de eles irem para o usuário.

Funções do Intercepting Filter
  • Podem interceptar um ou mais requests antes de eles chegarem ao servlet.
  • Podem interceptar um ou mais responses antes de eles retornarem para o cliente.
  • Filters são deployed declarativamente usando o DD.
  • Filters são modulares, então eles podem ser executados em cadeias.
  • Filters tem ciclo de vida gerenciados pelo Container.
  • Filters precisam ser implementados pelos métodos de callback do Container.
Princípios do Intercepting Filter
  • Os Intercepting Filter são baseados em:
- coesão.
- baixo acoplamento.
- aumentam o controle declarativo.
  • Controle declarativo habilitam a invocação da sequencia para ser facilmente atualizada.

Model, View, Controller (MVC)

Usa-se o padrão MVC para criar uma estrutura lógica que separa o código em três partes básicas de componentes(Modelo,Apresentação,Controle) em sua aplicação. Para aumentar a coesão de cada componente e habilitar para grande reuso, especialmente com componente de modelo.

Características Model, View, Controller (MVC)
  • View pode ser alterada independentemente do Controller e model.
  • Model components escondem detalhes internos(dados, estruturas), do view e do controller components.
  • Se o model adere ao restrito contrato(interface), então este componente pode ser reusado em outras áreas das aplicações, como GUI or J2ME.
  • Separação do código do model do código do controller, habilita para facil migração para usar componentes remotos de negócio.
Princípios Model, View, Controller (MVC)
  • Model, View, Controller são baseados em:
- separação de preocupações.
- baixo acoplamento
  • Aumenta a coesão de componentes individuais.
  • Aumenta a complexidade global da aplicação.(Isto é verdade porque embora componentes individuais sejam mais coesivos, MVC adiciona muitos novos componentes para a aplicação).
  • Minimiza o impacto de mudanças em outras camadas da aplicação.

Front Controller

Usa-se o padrão Front Controller para reunir o comum, oferecendo redundãncia, código de processamento de request em um único componente. Este habilita o controle da aplicação para ser mais coesivo e menos complexo.

Características Front Controller
  • Centraliza uma aplicação web, onde o request inicial é tratado em um único componente.
  • Usando o Front Controller com outros padrões, voce pode fornecer baixo acoplamento tornando a camada de apresentação dispatching declarative.
  • Um inconveniente do Front Controller(em seu próprio, sem o struts) isto é muito "barebones" comparado ao Struts. Para criar uma aplicação razoável do zero usando o padrão Front Controller, voce deveria terminar escrevendo muitas características já encontradas no struts.
Princípios Front Controller
  • O Front Controller é baseado em:
- esconder a complexidade.
- separação de preocupações.
- baixo acoplamento.
  • Aumenta a coesão em um componente de controle de aplicação.
  • Diminui a complexidade global da aplicação
  • Aumenta a manutenção da infra-estrutura do código.

8 comments:

João Sávio said...

Muito bom cara

Vc tem isso em .doc ou pdf?

Se puder me mandar joaosavio@gmail.com

Abração e parabens

Rafael said...

Muito bom cara

Vc tem isso em .doc ou pdf?

Se puder me mandar salerno.rafael@gmail.com

Abração e parabens

Diego said...

Parabens

Se possivel mande esse arquivo p meu mail tb: diegosantoscardozo@gmail.com

Obrigado

João Maria Alcantara said...

Valeu cara! Este post ajuda muito o pessoal que esta estudando, obrigado!

Vc tem o livro em pdf que vc estudou em português?

Se tive pode me enviar para joao210180@yahoo.com.br

Abraço!

Jéferson Machado said...

Que bom João, fico feliz em saber que meu resumo te ajudou, vou enviar o que tenho por email pra ti.

Abraço!

Rodrigo said...

Excelente Resumo!!! Parabens!!

Tem como vc passar em .doc ou pdf?
Se puder meu email e:
rodchiaradia@yahoo.com

Obrigado

Ricardo Barbosa said...

Muito me envia tb por email =x
rbrico@gmail.com
Vou fazer a prova amanha e to revisando pelo seu resumo!
;D

Blog do Cabral said...

Muito bom seu resumo, está de parabéns, porém
só fiquei com uma dúvida, javax.servlet.GenericServlet não é uma classe abstrata? no cap 4 do resumo está como interface.

Abraço!