O documento discute três APIs do Java EE 7 que simplificam o desenvolvimento de software: 1) JMS 2.0 simplifica o envio e recebimento de mensagens; 2) As APIs de Web Services melhoram a integração SOAP e REST; 3) O futuro trará ainda mais simplificação com menos código e configuração.
1. Novas APIs do
Java EE 7
E a batalha contra a complexidade
Helder da Rocha
helder@argonavis.com.br
2. Objetivos
Falar um pouco de complexidade do software e
apresentar três APIs do Java EE 7 que simplificam o
processo de desenvolvimento
Conteúdo
Breve reflexão sobre complexidade e entropia
JMS 2.0
APIs de Web Services (SOAP e REST)
O futuro?
2
6. Evolução das APIs
Uma API deve ser a mais simples possível
Contratos mais simples
Menos burocracia
Menos necessidade de documentação
Mas… problema inerente ao software: complexidade
Entropia sempre crescente
Sucesso depende do controle da complexidade
6
1.0
2.0
3.0
1.0
1.0
2.0
7. Java EE 7
Objetivo sempre presente na evolução das APIs:
Simplificar o uso!
Menor curva de aprendizado
Mais defaults, menos configuração
Menos, menos, menos
(até mesmo o JSF conseguiu ficar mais simples na Java EE 7 :-)
8. Java Message Service 1.0
Queue
Connection
Factory
Queue
Connection
Queue
Session
Queue
Sender
Queue
Receiver
Message
Queue
createSession()
jndi.lookup(queueFactory)
createConnection()
createMessage()
create() create()
receive()send()
jndi.lookup(queue)
API para enviar e receber
mensagens usa classes e
métodos diferentes para
domínios Queue e Topic
9. Java Message Service 1.1
Connection
Factory
Connection
SessionMessage
Producer
Message
Consumer
Message
Destination
createSession()
jndi.lookup(factory)
createConnection()
createMessage()
create() create()
receive()send()
jndi.lookup(destination)
API para enviar e receber
mensagens usa classes e
métodos iguais para
domínios Queue e Topic
10. Java Message Service 2.0
10
Connection
Factory
JMSContextJMSProducer JMSConsumer
Message
Destination
@Inject factory
createJMSContext()
createMessage()
create() create()
receive()send()
@Inject destination
@Inject em vez de JNDI
Menos código para enviar
e receber mensagens
11. Java Message Service 2.0
11
Connection
Factory
JMSContext
Destination
@Inject factory
createJMSContext()
receive()send()
@Inject destination
Menos código!
Menos código!
14. Pré-história do SOAP, parte 1
No princípio, Web Service eram simples
de codificar em XML
POST /ISBNService.jsp HTTP/1.0
Content-type: text/xml
Content-length: 90
<chamada>
<funcao>
<nome>getPrice</nome>
<param>2877142566</param>
</funcao>
</chamada>
HTTP/1.1 200 OK
Content-type: text/xml
Content-length: 77
<resposta>
<funcao>
<param>19.50</param>
</funcao>
</resposta>
ISBNService.jsp
ISBNClient
ISBNQuery
getPrice()
2877142566
19.50
BD
1
2
3
4
gera
requisição
gera
resposta
14
15. Pré-história do SOAP parte 2
XML-RPC: padronização dos tags para operações,
parâmetros, tipos, etc.
Criado no grupo de discussões xml-dev em 1998
<methodCall>
<methodName>getPrice</methodName>
<params>
<param>
<value><string>2877142566</string></value>
</param>
</param>
</methodCall> <methodResponse>
<params>
<param>
<value><double>19.5</double></value>
</param>
</param>
</methodResponse>
Resposta
Requisição
15
18. WSDL para descrever o serviço
Compare
com
a
mensagem
SOAP
mostrada
anteriormente
Informa
onde
está
o
serviço
(endpoint)
<?xml
version="1.0"
encoding="UTF-‐8"?>
<definitions
name="BookstoreService"
targetNamespace="http://mybooks.org/wsdl"
xmlns:tns="http://mybooks.org/wsdl"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<types>...</types>
<message
name="BookstoreIF_getPrice">
<part
name="String_1"
type="xsd:string"/>
</message>
<message
name="BookstoreIF_getPriceResponse">
<part
name="result"
type="xsd:decimal"/>
</message>
<portType
name="BookstoreIF">
<operation
name="getPrice"
parameterOrder="String_1">
<input
message="tns:BookstoreIF_getPrice"/>
<output
message="tns:BookstoreIF_getPriceResponse"/>
</operation>
</portType>
<binding
...
>
...</binding>
<service
...
>
...
</service>
</definitions>
19. Simplificação com JAX-WS
(escondendo a complexidade do XML)
19
@WebService
public
class
FilmeFacade
{
@PersistenceContext(unitName
=
"FilmesServiceSoap")
EntityManager
em;
public
List<Filme>
getFilmes()
{
String
jpql
=
"select
filme
from
Filme
filme";
Query
query
=
em.createQuery(jpql);
return
(List<Filme>)query.getResultList();
}
}
@Entity
public
class
Filme
implements
Serializable
{
@Id
private
Long
id;
private
String
titulo;
private
String
diretor;
private
Long
ano;
private
long
duracao;
private
String
imdb;
}
WEB-INF
web.xml
classes
FilmesServiceSoap.war
Deploy
Endpoint:
http://servidor/FilmesServiceSoap/FilmeFacadeService
20. Cliente SOAP
Com geração automática do
código SOAP
Ainda assim muito complexo:
a complexidade migrou para
a configuração
20
public
class
FilmeClient
{
public
static
void
main(String[]
args)
{
FilmeFacadeService
service
=
new
FilmeFacadeService();
FilmeFacade
proxy
=
service.getFilmeFacadePort();
listarFilmes(proxy.getFilmes());
}
public
static
void
listarFilmes(List<Filme>
filmes)
{
for(Filme
f
:
filmes)
{
System.out.println(f.getImdb()+":
"
+
f.getTitulo()
+
"("
+
f.getAno()
+
")");
System.out.println("
"
+
f.getDiretor());
System.out.println("
"
+
f.getDuracao()
+
"
minutosn");
}
}
} $
java
–jar
FilmeClient.jar
tt0081505:
The
Shining(1980)
Stanley
Kubrick
144
minutos
tt1937390:
Nymphomaniac(2013)
Lars
von
Trier
330
minutos
tt0069293:
Solyaris(1972)
Andrei
Tarkovsky
167
minutos
tt1445520:
Hearat
Shulayim(2011)
Joseph
Cedar
21. Cliente em container
21
@Named("filmesBean")
public
class
FilmesManagedBean
{
@WebServiceRef(wsdlLocation=
"http://localhost:8080/FilmesServiceSoap/FilmeFacadeService?wsdl")
private
FilmeFacadeService
service;
private
List<Filme>
filmes;
@PostConstruct
public
void
init()
{
FilmeFacade
proxy
=
service.getFilmeFacadePort();
this.filmes
=
proxy.getFilmes();
}
…
}
<h1>Lista
de
Filmes</h1>
<h:dataTable
value="#{filmesBean.filmes}"
var="filme”>
<h:column>
<f:facet
name="header">IMDB</f:facet>
<a
href="http://www.imdb.com/title/#{filme.imdb}">
#{filme.imdb}</a>
</h:column>
<h:column>
<f:facet
name="header">Título</f:facet>
#{filme.titulo}
</h:column>
...
</h:dataTable>
CDI Managed Bean
JSF Facelets
Mais simples. Menos configuração
22. RESTful Web Services
REST ~= Infraestrutura de um website
recursos (páginas), links, hierarquia
representações de dados e tipos (URIs, MIME)
vocabulário de operações do protocolo HTTP (GET, POST, …)
URIs ~= objetos
pais.estado.cidade
==
http://servidor/aplicacao/pais/estado/cidade/
Representações
XML, JSON, CSV, etc.
Métodos HTTP permitem operações CRUD
Create: POST /pais/estado (<estado>SP</estado>, no corpo)
Retrieve: GET /pais/estado/SP (Retrieve All com GET /pais/estado)
Update: PUT /pais/estado/PB
Delete: DELETE /pais/estado/PB
22
23. JAX-RS
JAX-RS : API Java para RESTful WebServices
Componentes
Subclasse de Application: configuração
Root resource class: fachada de serviços
Resource method: associados a métodos HTTP (@GET, @POST, etc.)
Providers: produzem ou consomem representações de entidades
em outros formatos (ex: XML, JSON)
JAX-RS usa anotações para configurar os componentes
@ApplicationPath na subclasse de Application
@Path nos Root resource classes
@GET, @POST, etc e @Path nos Resource methods
@Produces, @Consumes nos Providers
@Context para injetar diversos tipos de contexto do ambiente Web
23
24. Path templates e @PathParam
@Path templates
@Path("/filmes/{imdb}")
Aceita por exemplo: http://abc.com/war/app/filmes/tt0066921
Parâmetros @PathParam
@Path("/filmes/{imdb}")
public
class
FilmesIMDBResource
{
@GET
@Produces("text/xml")
public
Filme
getFilme(@PathParam("imdb")
String
codigoIMDB)
{
return
entity.getFilmeByIMDBCode(codigoIMDB);
}
}
24
25. Diferentes representações de objetos
25
Representação em JSON
{
"@numero": 145,
"nome": "Jeeves",
[ "telefone": {
"ddd": 11, "numero": 34567890
} ]
}
Representação em XML
<pessoa xmlns="http://pessoa" numero="145">
<nome>Jeeves</nome>
<telefone>
<ddd>11</ddd>
<numero>34567890</numero>
</telefone>
</pessoa>
Pessoa pessoa = new Pessoa();
pessoa.numero = 145;
pessoa.nome = "Jeeves";
pessoa.telefone[0] = new Telefone();
pessoa.telefone[0].ddd = 11;
pessoa.telefone[0].numero = 34567890;
class Pessoa {
int numero;
String nome;
Telefone[] telefones =
new Telefone[3];
}
class Telefone {
int ddd;
int numero;
}
Classes
Objetos
em Java
application/xml application/json
26. JAXB
Java API for XML Binding
Mapeia classes Java a XML Schema
Classes mapeadas a XML Schema (ferramentas xjc e schemagen)
Objetos mapeados a documentos XML (através da API javax.xml.bind e
operações de serialização em XML (marshalling e unmarshalling)
XML
Schema
Classes
Java
Binding
xjc
schemagen
Documentos
(instâncias
XML)
Objetos
(instâncias
Java)
Marshalling
unmarshal()
marshal()
26
27. JAXB: exemplo de classe anotada
27
@XmlSchema(namespace
=
"http://filmes.argonavis.com/")
package
com.argonavis.filmes.generated;
@XmlRootElement
public
class
Sala
implements
Serializable
{
private
List<Assento>
assentos;
private
String
nome;
private
int
lotacao;
@XmlElementWrapper
@XmlElement(name="assento")
public
List<Assento>
getAssentos()
{
return
assentos;
}
…
}
Sem @XmlElementWrapper
<sala>
<assentos>…</assentos>
<assentos>…</assentos>
</sala>
Com @XmlElementWrapper
<sala>
<assentos>
<assento>…</assento>
<assento>…</assento>
</assentos>
</sala>
28. JAXB Marshal / Unmarshal
Unmarshalling = XML àJava
JAXBContext
jc
=
JAXBContext.newInstance(
"com.argonavis.filmes.gen"
);
Unmarshaller
u
=
jc.createUnmarshaller();
Filme
filme
=
(Filme)u.unmarshal(
new
File(
"tt1937390.xml"
)
);
Marshalling = Java àXML
JAXBContext
jc
=
JAXBContext.newInstance(
"com.argonavis.flmes.gen"
);
Filme
filme
=
ObjectFactory.createFilme();
filme.setAno(2014);
//
alterando
objeto
Marshaller
m
=
jc.createMarshaller();
m.marshal(
filme,
System.out
);
28
29. JSON Binding!
Substituir o provedor JAXB default por EclipseLink MOXy:
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
Configuração de JAXBContext
Map properties = new HashMap();
props.put("eclipselink.media-type", "application/json");
JAXBContext ctx = JAXBContext.newInstance(new Class[] { Produto.class }, props);
JSON à Java
UnMarshaller u = ctx.createUnMarshaller();
Produto produto= u.unmarshal(new StreamSource(“produto123.json”));
Java à JSON
Marshaller m = ctx.createMarshaller();
m.marshal(produto, System.out);
29
Haverá suporte nativo
a JSON binding no
Java EE 8 (2016)
30. Cliente REST com java.net
Cliente HTTP!
URL
url
=
new
URL("http://localhost:8080/ctx/app/imdb/tt0066921");
HttpURLConnection
conn
=
(HttpURLConnection)
url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Accept",
"application/xml");
if
(conn.getResponseCode()
!=
200)
{
throw
new
RuntimeException("Erro
:
"
+
conn.getResponseCode());
}
BufferedReader
br
=
new
BufferedReader(new
InputStreamReader((conn.getInputStream())));
String
linha
=
br.readLine();
System.out.println("Dados
recebidos:
"
+
linha);
conn.disconnect();
JAXBContext
jc
=
JAXBContext.newInstance(Filme.class);
Unmarshaller
u
=
jc.createUnmarshaller();
Filme
filme
=
(Filme)
u.unmarshal(new
StringReader(linha));
System.out.println(filme.getIMDB());
…
30
31. Cliente Jersey*
Ainda mais simples
ClientConfig
config
=
new
DefaultClientConfig();
Client
client
=
Client.create(config);
URI
baseURI
=
UriBuilder.fromUri("http://localhost:8080/ctx").build();
WebResource
service
=
client.resource(baseURI);
Filme
filme
=
service.path("app")
.path("filme/imdb/tt0066921")
.accept(MediaType.APPLICATION_XML)
.get(Filme.class);
System.out.println(filme.getIMDB());
System.out.println(filme.getTitulo());
System.out.println(filme.getDiretor());
* Existem outras alternativas. Veja RESTEasy
31
32. Cliente mobile (iPhone)
REST é melhor alternativa para Web Services que fazem
integração como outras plataformas
32
GET
http://192.168.1.25/festival/webapi/filme
Glassfish 4.0
1) Cliente REST escrito em Objective-C
rodando em iOS 7 gera requisição
2) Glassfish gera resposta HTTP
com lista de filmes em JSON
3) iPhone extrai dados e
preenche UITableView
33. O futuro
Java EE 8 promete uma vida menos complexa
API de segurança unificada
API de transações unificada
CDI com papel central em todas as aplicações
JSON binding nativo
Melhor integração com WebSockets
Mas, ...
A entropia continua a crescer... + linguagens + bugs +
problemas + ameaças + horizontes + iOT + ... a luta continua!