O documento apresenta uma arquitetura de aplicação web rica utilizando AngularJS no frontend e Java EE no backend, com as seguintes tecnologias:
1) Serviços RESTful implementados com JAX-RS para comunicação entre frontend e backend;
2) Uso de WebSocket para comunicação full-duplex;
3) Integração de AngularJS com Java EE utilizando JSON para troca de dados.
4. Client-side vs. Server-side
• Server-side
• Tudo é processado no
servidor
• Mais stateful
• Fraca escalabilidade
• Client-side
• Complexo e dinâmico
• Mais stateless
• Maior escalabilidade
5. Ascenção do Javascript
• O debate cliente ‘leve' vs cliente ‘pesado' é antigo…
• Frameworks web server-side mandaram por um tempo
(Struts, Spring, MVC, JSF)
• Ajax foi uma mudança suave para o client-side (GWT,
Vaadin)
• Rich clients estão voltando voltaram, graças ao JavaScript/
HTML5
• Motores Javascript melhoraram muito
• Melhores ferramentas desenvolvimento
• Melhores padrões (CSS3, HTML5, Websocket)
7. Arquitetura Rich Client
• Similar a arquiteturas cliente/servidor
• Client responsável pela UI, input, validação, lógica e
estado
• Server responsável pela lógica de negócio, modelo de
domínio, persistência
• Web/HTTP é a cola que conecta client e server
• Protocolos de comunicação comuns
• REST na maioria dos casos
• WebSocket quando precisa de comunicação full-duplex
• Ferramentas Javascript suportam REST muito bem, mas
ainda não WebSocket
• O formato comum (talvez ideal?) de troca de dados é JSON
9. Arquitetura REST
• Características:
• ︎Protocolo cliente/servidor sem estado (HTTP)
• ︎Operações bem definidas (GET, POST, PUT)
• ︎Sintaxe universal para identificação de recursos
(URL)
• ︎Transferência de informações em formato padrão
(XML, HTML, JSON)
• Web Services que seguem a arquitetura REST são
denominados RESTful
11. HATEOAS
• Hypermedia As The Engine of Application State
• Clientes somente precisam saber a URI root da aplicação e os media
types utilizados
• Descrevem o estado atual da aplicação e como navegar para o próximo
estado
12. Java EE é uma ótima plataforma server-
side para esta arquitetura
13. Java EE History
J2EE 1.3
CMP,
Connector
Architecture
J2EE 1.4
Web
Services
Mgmt,
Deployment,
Async
Connector
Java EE 5
Ease of
Development,
EJB 3, JPA,
JSF, JAXB,
JAX-WS,
StAX, SAAJ
Java EE 6
Pruning,
Extensibility
Ease of Dev,
CDI, JAX-RS
Web$Profile$
$
Servlet 3,
EJB 3.1 Lite
!
Java EE 7
!
JMS 2,
Batch, TX,
Concurrency,
Interceptor,
WebSocket,
JSON!
Web$Profile$
$
JAX-RS 2
!
JAX-RPC, CMP/
BMP, JSR 88
15. Java EE + JavaScript
EJB 3
Servlet
CDI
JPA
JAX-RS
BeanValidation
Java API for
WebSocket
Java API for
JSON
JMS JTA
JavaScript/HTML5
JAXB
JCA
16. JAX-RS
• Suporte a RESTful em Java
• API padronizada
• Programação declarativa
• Abstrações para implementação no server e client
• Serviços implementados via POJO
• Configuração via anotações
• @Path, @GET, @POST, @PUT, @DELETE, @PathParam,
@QueryParam, @Produces, @Consumes, etc
• Plugável e extensível
• Providers, filters, interceptors, validators
• Suporte a processamento assíncrono
• Integrado com as tecnologias do Java EE
17. JAX-RS
@Path Define a URI para ser utilizada pelo endpoint
@GET Determina acesso ao serviço via HTTP GET
@POST Determina acesso ao serviço via HTTP POST
@PUT Determina acesso ao serviço via HTTP PUT
@DELETE Determina acesso ao serviço via HTTP DELETE
@HEAD Determina acesso ao serviço via HTTP HEAD
@PathParam Define o mapeamento do valor informado na URI para um
determinado parâmetro de método
@QueryParam Define o mapeamento do valor informado na query string para um
determinado parâmetro de método
@Consumes Define um determinado MIME type para recebimento de dados
pelo serviço
@Produces Define um determinado MIME type para envio de dados pelo
serviço
@Provider Define um determinado componente para auxiliar no JAX-RS
runtime.
@ApplicationPath Determina o root path de uma aplicação JAX-RS
18. Manipulação de Parâmetros
• Além do @PathParam há outras cinco anotações que
permitem extrair informação de um request
• @QueryParam e @DefaultValue
• Extraem dados de um query string (?nome=valor&nome=valor)
• @FormParam
• Extrai dados de um formulário (applicaton/x-www-form-urlencoded)
• @CookieParam
• Extrai dados de cookies (pares nome=valor)
• @HeaderParam
• Extrai dados de cabeçalhos HTTP
• @MatrixParam
• Extrai dados de segmentos de URL
19. Validação de Dados
• Os dados enviados para métodos em classes de resource
podem ser validados através da API Bean Validation, que
é configurada via anotações
@POST
@Path("/criar")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public void criarFilme(
@NotNull @FormParam("titulo") String titulo,
@NotNull @FormParam("diretor") String diretor,
@Min(1900) @FormParam("ano") int ano) { ... }
@Pattern(regexp="tt[0-9]{5-7}")
private String imdbCode;
20. Conversão de Dados
• ParamConverterProvider pode ser utilizado para gerenciar a
conversão de objetos customizados Object para String e vice-versa
• Por exemplo, pode ser utilizado para produzir um objeto java.util.Date a partir de
uma String formatada.
@Provider
public class MyBeanConverterProvider implements ParamConverterProvider {
@Override
public <T> ParamConverter<T> getConverter(
Class<T> clazz, Type type, Annotation[] annotations) {
if (clazz.getName().equals(MyBean.class.getName())) {
return new ParamConverter<T>() {
@Override
public T fromString(String value) {...}
@Override
public String toString(T bean) {...}
};
}
return null;
}
}
21. Tratamento de Exceções
• Geração e lançamento da exceção customizada
• Exemplo de definição de exceção customizada
public class CustomNotFoundException extends WebApplicationException {
public CustomNotFoundException() {
super(Responses.notFound().build());
}
}
@Path("items/{itemid}/")
public Item getItem(@PathParam("itemid") String itemid) {
Item i = getItems().get(itemid);
if (i == null) {
throw new CustomNotFoundException("Item, " +
itemid + ", is not found");
}
return i;
}
23. Filtros
• Filtros podem ser server side e/ou client side
• ContainerRequestFilter, ContainerResponseFilter
• ClientRequestFilter, ClientResponseFilter
public class AuthorizationRequestFilter implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext requestContext)
throws IOException {
final SecurityContext securityContext =
requestContext.getSecurityContext();
if (securityContext == null ||
!securityContext.isUserInRole("privileged")) {
requestContext.abortWith(Response.status(
Response.Status.UNAUTHORIZED)
.entity("User cannot access the resource.").build());
}
}
}
24. Interceptadores
• Existem dois tipos de interceptors (Reader e Writer)
// @Compress annotation is the name binding annotation
@NameBinding
@Retention(RetentionPolicy.RUNTIME)
public @interface Compress {}
@Path("helloworld")
public class HelloWorldResource {
@GET @Path("too-much-data")
@Compress
public String getVeryLongString() {...}
}
@Compress
public class GZIPWriterInterceptor implements WriterInterceptor {
@Override
public void aroundWriteTo(WriterInterceptorContext context)
throws IOException, WebApplicationException {...}
}
25. @Context
• @Context pode ser utilizado para injetar diversos objetos
contextuais disponíveis em uma requisição ou resposta HTTP
• Objetos da Servlet API
• ServletConfig
• ServletContext
• HttpServletRequest
• HttpServletResponse
• Objetos da JAX-RS API
• Application
• UriInfo
• Request
• HttpHeaders
• SecurityContext
• Providers
@Context
Request request;
@Context
UriInfo uriInfo;
@PUT
public metodo(@Context HttpHeaders headers) {
String m = request.getMethod();
URI ap = uriInfo.getAbsolutePath();
Map<String, Cookie> c = headers.getCookies();
}
@GET @Path("auth")
public login(@Context SecurityContext sc) {
String userid =
sc.getUserPrincipal().getName();
if (sc.isUserInRole("admin")) { ... }
}
26. Hypermedia Support
• JAX-RS oferece um modelo para suportar HATEOAS por meio
de suporte à hypermedia
• Em cada mensagem de resposta, deve ser incluído os links
para a próxima mensagem
• Utilizando este suporte, a aplicação consegue definir todo o
modelo de navegação via HTTP
@POST
@Consumes({"application/json", "application/xml"})
@Produces({"application/json", "application/xml"})
public Response create(Article article) {
Article created = articleDao.create(article);
return Response.ok(created)
.link("link-URI", "link-rel")
.links(produceLinks(created))
.build();
}
private Link[] produceLinks(Article article) {...}
27. Integração com CDI
• JAX-RS integra-se muito bem com as tecnologias da
plataforma Java Enterprise, especialmente com os
componentes EJBs e CDI.
• CDI beans podem ser injetados diretamente nos
resources. Providers e Application terão comportamento
singleton ou @ApplicationScoped
@Path("/cdibean")
public class CdiBeanResource {
@Inject MyOtherCdiBean bean; // CDI injected bean
@GET
@Produces("text/plain")
public String getIt() {
return bean.getIt();
}
}
28. Integração com EJB
• Exemplo de integração com EJB
@Local
public interface LocalEjb {
@GET
@Produces("text/plain")
public String getIt();
}
@Stateless
@Path("/stateless")
public class StatelessEjbResource implements LocalEjb {
@Override
public String getIt() {
return "Hi Stateless!";
}
}
29. Cache Control
• JAX-RS suporta configurações para controle de caching de responses
HTTP por meio da classe CacheControl
@GET
@Path("{id}")
public Response read(@PathParam("id") int id) {
Article article = articleDao.findById(id);
CacheControl cacheControl = new CacheControl();
cacheControl.setMaxAge(60);
return Response.ok(article)
.cacheControl(cacheControl)
.build();
}
30. Chamadas Assíncronas
• Possibilita o processamento multithread no servidor,
aumentando o seu throughput
• Libera a thread do servidor para executar outras tarefas
• @Suspended indica que o método será executado de
maneira assíncrona
• Possível configurar timeout
@Path(“Async") @RequestScope
public class AsyncResource {
@GET
public void asyncGet(@Suspended final AsyncResponse asyncResponse) {
new Thread(new Runnable() {...}).start();
}
}
31. WebSocket
• Oferece comunicação bi-direcional (full-duplex) através de
uma simples conexão TCP
• Inicia através de um hand-shake através do protocolo
HTTP, mas as conversações utilizam o protocolo
WebSockets.
• Suporte requisições assíncronas
• Perfeito para aplicações como chat e jogos
• Utiliza as tecnologias web existentes
35. Java API for WebSocket
• Programação declarativa com anotações
• Client and server-side
• Powerful API
• @ServerEndpoint, @OnOpen, @OnClose, @OnMessage,
@OnError, Session, Remote
• Plugável e extensível
• Encoders, decoders, sub-protocols
• Lifecycle callback handlers
• Permite empacotá-los em aplicações Java EE
36. Java API for WebSocket
• Define o endpoint do servidor WebSocket para conexão
pelos clientes
@ServerEndpoint(”/chat”)
public class ChatServer {
@OnOpen
public void onOpen(Session peer) {...}
@OnClose
public void onClose(Session peer) { ... }
@OnMessage
public void message(String message, Session client)
throws IOException {...}
@OnError
public void error(Session session, Throwable t) { ... }
}
37. Java API for WebSocket
• Exemplo de cliente em JavaScript
var wsUri = "ws://" + document.location.hostname + ":" +
document.location.port +
document.location.pathname + "chat";
var websocket = new WebSocket(wsUri);
websocket.onopen = function(evt) { onOpen(evt) };
websocket.onmessage = function(evt) { onMessage(evt) };
websocket.onerror = function(evt) { onError(evt) };
38. JSON
• JavaScript Object Notation
• Pode ser codificado diretamente em String e processado com
métodos como split(), substring(), indexOf() dentre outros
• Java EE 7 disponibiliza um API para construir objetos JSON e
para converter strings JSON em mapas
• É um par de APIs de baixo nível (não é mapeamento objeto-JSON)
• Existem várias implementações que fazem mapeamento (binding)
objeto-JSON automático (não são parte do Java EE)
• MOXy, Jettison, Jersey, Jackson, etc.
{id:123, cidade:”Paris”, voos:[“M344”,”J919”]}
39. Java API for JSON
• API para parser e geração de objetos JSON definida pelo
Java EE
• Object Model API - javax.json
• Análogo a DOM: estrutura em árvore; I/O streaming via
decorators
• JsonObject: representa um objeto JSON
• JsonArray: representa um array JSON
• Leitura e gravação usando JsonReader e JsonWriter
• JSON Streaming API - javax.json.stream
• Análogo a SAX: leitura sequencial (baixo nível)
• JsonParser: permite ler um stream JSON e capturar eventos
• JsonGenerator: métodos para criar uma estrutura JSON
40. Java API for JSON
• JSON Object Model API
[
{
"type": "home ,
"number": "212 555-1234"
},
{
"type": "fax ,
"number": "646 555-4567"
}
]
JsonArray value =
Json.createArrayBuilder()
.add(Json.createObjectBuilder()
.add("type", "home")
.add("number", "212 555-1234")
)
.add(Json.createObjectBuilder()
.add("type", "fax")
.add("number", "646 555-4567")
)
.build();
42. JAXB
• JAXB beans permitem reutilizar o mesmo JavaBean
para gerar representações JSON e XML no response
@XmlRootElement
public class MyJaxbBean {
public String name;
public int age;
...
}
@GET
@Produces("application/json")
public MyJaxbBean getMyBean() {
return new MyJaxbBean("Agamemnon", 32);
}
{"name":"Agamemnon", "age":"32"}
43. AngularJS é uma ótima alternativa para
implementação Web rich client
44. AngularJS
• Framework JavaScript MVW* client-side para desenvolver
aplicações web modernas e dinâmicas
• A primeira versão open-source foi liberada em 2010 e
desde então ele é mantido pela Google e pela comunidade
• Aproximadamente 2 releases mensais, projeto altamente
ativo
• O que faz o AngularJS ser especial?
53. Demo
• Java EE + AngularJS
• https://github.com/rcandidosilva/javaee-javascript
54. Conclusões…
• Clientes Javascript/HTML5 estão conquistando
desenvolvedores
• Comunicação entre cliente e servidor em JSON via REST
ou WebSocket
• Java EE funciona muito bem como backend para clientes
ricos em Javascript, especialmente JAX-RS, Java API para
WebSockets, e JSON-P
• Enjoy it ;)