Post on 15-Jul-2015
ROME 27-28 march 2015
Java EE facile con Spring Boot
l.bennardis@email.it
Luigi Bennardis
ROME 27-28 march 2015 - Luigi Bennardis
Agenda
Le caratteristiche di Spring Boot
La soluzione applicativa
Descrizione
Tecnologie integrate
Ambiente di sviluppo
Implementazione
Conclusioni
Appendice: JAX-RS (Jersey) & JSR 330
Link
ROME 27-28 march 2015 - Luigi Bennardis
Le caratteristiche di Spring Boot
Semplificazione dello sviluppo applicativo basato su SPRING
• realizzare soluzioni eseguibili in modalità stand-alone e/o in container J2EE
Applicazione del Paradigma «convention over configuration»
• Semplificazione dello sviluppo senza ricadute sulla flessibilità
• Eliminazione dei file di configurazione
Vista semplificata di Spring
Numerose funzionalità di default facilmente sostituibili
Annotazioni speciali
Gestione semplificata delle dipendenze
Inclusione del container di esecuzione
«Auto-Configurazione» delle librerie di dipendenza
ROME 27-28 march 2015 - Luigi Bennardis
La soluzione applicativa: descrizioneServizio Web di prenotazione di esami universitari
Componenti REST Controller: tecnologia di esposizione del servizio web & BL Service Facade: espone funzioni a grana grossa Data Persistence: espone funzioni a grana fine di persistenza dati Message Queue: espone funzioni a grana fine di scrittura di messaggi
ROME 27-28 march 2015 - Luigi Bennardis
La soluzione applicativa: tecnologie integrate
Servlet Container in modalità embedded Tomcat 8 Undertow 1.1
Application Server – Java EE Tomcat EE 2.0
HornetQ – JMS Sistema di messaggistica asincrona open source Implementa la specifica JMS Server/Integrato in AS J2EE/Embedded
H2 – JDBC Database open source – Java Bassa impronta binaria Server/In memory/Embedded
ROME 27-28 march 2015 - Luigi Bennardis
La soluzione applicativa: tecnologie integrate
Hibernate – ORM – JPA
Framework di ORM (Object Relational Mapping) Implementa la specifica JPA Realizza la persistenza sul protocollo JDBC
Atomikos – JTA
Open Source Transaction Manager Realizza la transazionalità distribuita XA (JDBC-JMS)
Cloud Foundry
Progetto Open Source di “Open Cloud” Deliver di piattaforme applicative come servizi (PAAS) Semplifica: distribuzione/esecuzione/scalabilità
ROME 27-28 march 2015 - Luigi Bennardis
La soluzione applicativa: ambiente di sviluppo
Java JDK 1.8
Spring (Luna) – STS (Spring Tool Suite)
Maven 3
Spring Boot 1.2 (<Spring-Boot-Starter>)
Servlet 3.1
Java Transaction Api
Deployment su AS EE (Tomcat EE 2.0)
Eclipse Cloud Foundry Integration
ROME 27-28 march 2015 - Luigi Bennardis
La soluzione applicativa: implementazione
Embedding del servlet container
Integrazione H2 Hibernate e JSR 250
Integrazione HornetQ
Deploy su Application Server EE (Tomcat EE)
Integrazione Atomikos, transazionalità distribuita
Deploy su Cloud Foundry
ROME 27-28 march 2015 - Luigi Bennardis
<!– PLUG-IN BOOT PER MAVEN --><plugin>
<groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId>
</plugin><!-- DEFAULT TOMCAT 8.0 EMBEDDED + SPRING MVC--><dependency>
<groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency><!-- UNDERTOW EMBEDDED--><dependency>
<groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId>
</dependency><dependency>
<groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-undertow</artifactId>
</dependency><dependency>
<groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId>
</dependency>
Maven: plugin per Spring Boot e dichiarazione delle dipendenze
Implementazione → Embedding del container
ROME 27-28 march 2015 - Luigi Bennardis
@SpringBootApplication // @Configuration @EnableAutoConfiguration @ComponentScanpublic class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
} }
@SpringBootApplicationCorrisponde alle annotazioni di Spring:
@Configuration @EnableAutoConfiguration @ComponentScanDeve essere definita in un package di rootEsegue l’auto-configurazione delle librerie dichiarate nel classpathEsegue la scansione del package per rilevare automaticamente le classi da iniettare nel contesto di Spring
SpringApplication: Iniezione di argomenti da linea di comando
Classe di avvio Spring-Boot da linea di comando
Implementazione → Embedding del container
ROME 27-28 march 2015 - Luigi Bennardis
@RestController //@Controller @ResponseBodypublic class Controller {
@RequestMapping("/prenotaEsame") public String servletTest(
@RequestParam(value="matricola") String matricola, @RequestParam(value="esame") String esame) {
return "Servlet eseguita param: codice esame: " + esame + " matricola studente: " + matricola ;
} }
@RestControllerMarca la classe come Web Controller. Corrisponde alle annotazioni
@Controller: gestisce la Request HTTP@ResponseBody: indirizza il valore di ritorno a una Web Response
@RequestMappingMappa la Web Request “/<url>” sul metodo “servletTest”
@RequestParamMappa i valori dei parametri della Request sulle variabili di firma del metodo
RestController : classe che gestisce Request e Response HTTP
Implementazione → Embedding del container
ROME 27-28 march 2015 - Luigi Bennardis
mvn spring-boot:run
Esecuzione da Eclipse (Tomcat embedded) e console
.....
Tomcat initialized with port(s): 8080 (http)Starting service TomcatStarting Servlet Engine: Apache Tomcat/8.0.20Initializing Spring embedded WebApplicationContextRoot WebApplicationContext: initialization completed in 2014 msMapping servlet: 'dispatcherServlet' to [/].....Mapped"{[/prenotaEsame],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.lang.Stringit.luigibennardis.boot.demo.rest.Controller.servletTest(java.lang.String,java.lang.String).....Tomcat started on port(s): 8080 (http) Started Application in 3.942 seconds (JVM running for 8.652).....Initializing Spring FrameworkServlet 'dispatcherServlet'FrameworkServlet 'dispatcherServlet': initialization startedFrameworkServlet 'dispatcherServlet': initialization completed in 32 ms
Implementazione → Embedding del container
Eclipse: Run & Console
ROME 27-28 march 2015 - Luigi Bennardis
mvn spring-boot:run
Esecuzione da Eclipse (Undertow embedded) e console
.....Undertow started on port(s) 8080 (http)Started Application in 3.942 seconds (JVM running for 8.652).....Initializing Spring FrameworkServlet 'dispatcherServlet'FrameworkServlet 'dispatcherServlet': initialization startedFrameworkServlet 'dispatcherServlet': initialization completed in 32 ms
Implementazione → Embedding del container
Eclipse: Run & Console
ROME 27-28 march 2015 - Luigi Bennardis
<!-- JAVA PERSISTENCE API SUPPORT --><dependency>
<groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- H2 DATABASE --><dependency>
<groupId>com.h2database</groupId><artifactId>h2</artifactId>
</dependency>
<spring-boot-starter-data-jpa>Configura la specifica JPA nel contesto di Spring
<h2>Configura un datasource per l’istanza H2 eseguita in modalità embedded
Maven: dichiarazione delle dipendenze
Implementazione → H2 - Hibernate
ROME 27-28 march 2015 - Luigi Bennardis
@Service public class ServicePrenotazioneEsame {
private final IRepositoryPrenotazioneEsame prenEsameRepo;
@Autowiredpublic ServicePrenotazioneEsame(
IRepositoryPrenotazioneEsame localRepo) { this.prenEsameRepo = localRepo;
}
public void registraPrenotazione(String codPrenotazione, String codEsame, String matricolaStud) {
this.prenEsameRepo.save(new EntityPrenotazioneEsame(codPrenotazione, codEsame, matricolaStud)); }
}
@Service Business Service Facade che incapsula le funzioni di grana fine esponendo alla logica applicativa quelle a grana più grossa
@AutowiredInietta la classe marcata nel contesto Spring
Service Facade:
metodo di registrazione della prenotazione
Implementazione → H2 - Hibernate
ROME 27-28 march 2015 - Luigi Bennardis
@RestControllerpublic class Controller {
@Autowiredprivate ApplicationContext context;
@RequestMapping("/prenotaEsame") public String prenotaEsame(@RequestParam(value="matricola") String matricola,@RequestParam(value="esame")
String esame) { ServicePrenotazioneEsame service = context.getBean(ServicePrenotazioneEsame.class); IRepositoryPrenotazioneEsame repository = context.getBean(IRepositoryPrenotazioneEsame.class);
service.registraPrenotazione(codPrenotazione, esame, matricola); }
@RequestMapping("/prenotazioniFatte") public String prenotazioniFatte()
{ IRepositoryPrenotazioneEsame repository = context.getBean(IRepositoryPrenotazioneEsame.class);
return "PRENOTAZIONI PRESENTI IN BASE DATI: " + " <BR> " + repository.count() + " <BR> " + repository.findAll(); }
}
Controller:chiamata al metodo esposto dal Service Facade
Implementazione → H2 - Hibernate
ROME 27-28 march 2015 - Luigi Bennardis
@Component public class UnitTestCaricaTipologiche {
private final IRepositoryEsame esameRepo;
@Autowiredpublic UnitTestCaricaTipologiche(IRepositoryEsame localRepo) { this.esameRepo = localRepo;
} @PostConstruct // ANNOTAZIONE JSR 250 (SPECIFICA JAVA EE 5) ESEMPIO DI HOOK DEL CICLO DI VITA. public void inizializzaBaseDati() throws Exception {
System.out.println("INIZIALIZZAZIONE TABELLA TIPOLOGICA ESAME");
this.esameRepo.save(new EntityEsame("00001", "Ingegneria Civile")); this.esameRepo.save(new EntityEsame("00002", "Ingegneria Elettronica")); this.esameRepo.save(new EntityEsame("00003", "Ingegneria Meccanica")); this.esameRepo.save(new EntityEsame("00004", "Ingegneria Informatica"));
System.out.println("TABELLA TIPOLOGICA ESAME-> INIZIALIZZAZIONE COMPLETA RECORD: " + esameRepo.count());
} }
@PostConstructMarca il metodo ehe la classe esegue dopo essere stata istanziata
H2 Emdedded -> JSR 250 LIFECICLE HOOKSGestione dell’Inizializzazione del database (UT/IT)
Implementazione → H2 - Hibernate
ROME 27-28 march 2015 - Luigi Bennardis
.....
.....
Building JPA container EntityManagerFactory for persistence unit 'default'HHH000204: Processing PersistenceUnitInfo [..........
HHH000412: Hibernate Core {4.3.8.Final}HHH000206: hibernate.properties not foundHHH000021: Bytecode provider name : javassistHCANN000001: Hibernate Commons Annotations {4.0.5.Final}HHH000400: Using dialect: org.hibernate.dialect.H2DialectHHH000397: Using ASTQueryTranslatorFactoryHHH000227: Running hbm2ddl schema exportHHH000230: Schema export complete
INIZIALIZZAZIONE TABELLA TIPOLOGICA ESAMETABELLA TIPOLOGICA ESAME-> INIZIALIZZAZIONE COMPLETA RECORD: 4..........
Esecuzione da Eclipse e console di output
Implementazione → H2 - Hibernate
mvn spring-boot:run
Eclipse: Run & Console
ROME 27-28 march 2015 - Luigi Bennardis
<!-- SPRING JMS --><dependency>
<groupId>org.springframework</groupId><artifactId>spring-jms</artifactId>
</dependency><!-- HORNETQ --><dependency>
<groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-hornetq</artifactId>
</dependency><dependency>
<groupId>org.hornetq</groupId><artifactId>hornetq-jms-server</artifactId>
</dependency><!-- TOMEE EXTERNAL --><dependency>
<groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId><scope>provided</scope>
</dependency><!– PACKAGING J2EE--><packaging>war</packaging>
Maven: dichiarazione delle dipendenze e packaging J2EE
Implementazione → HornetQ
ROME 27-28 march 2015 - Luigi Bennardis
@SpringBootApplication public class Application extends SpringBootServletInitializer{
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class); }
}
@SpringBootServletInitializerInizializza il contesto Spring-Boot nel Container J2EE
Esecuzione di Spring Boot nel servlet container J2EE
Implementazione → HornetQ
ROME 27-28 march 2015 - Luigi Bennardis
package it.luigibennardis.boot.demo.rest;
import org.springframework.jms.annotation.JmsListener; import org.springframework.stereotype.Component;
@Componentpublic class CodaPrenotazioneEsame {
@JmsListener(destination = "codaPrenotazioneEsami") public void onMessage(String content) {
System.out.println("MESSAGGIO PUBBLICATO SULLA CODA codaPrenotazioneEsami :" + content); }
}
spring.hornetq.mode=embeddedspring.hornetq.embedded.enabled=truespring.hornetq.embedded.queues=codaPrenotazioneEsami
@ComponentMarca la classe per essere iniettata nel contesto di Spring in fase di scansione del classpath
@JmsListenerMarca il metodo che corrisponde al target del listener JMS
Listener JMS: implementazione
Implementazione → HornetQ
HornetQ: direttive di configurazione
ROME 27-28 march 2015 - Luigi Bennardis
@Servicepublic class ServicePrenotazioneEsame {
//.....@Autowiredpublic ServicePrenotazioneEsame(IRepositoryPrenotazioneEsame localRepo,JmsTemplate jmsTemplate) {
this.prenEsameRepo = localRepo; this.jmsTemplate = jmsTemplate;
}
public void registraPrenotazione(String codPrenotazione, String codEsame, String matricolaStud) {
//PERSISTENZA DEI DATI SUL DATABASE this.prenEsameRepo.save(new EntityPrenotazioneEsame(codPrenotazione, codEsame, matricolaStud));
//PUBBLICAZIONE DEL MESSAGGIO SULLA CODA this.jmsTemplate.convertAndSend("codaPrenotazioneEsami", codPrenotazione + "|" + codEsame + "|" +
matricolaStud); }
}
Service Facade:chiamata al metodo di scrittura del messaggio
Implementazione → HornetQ
ROME 27-28 march 2015 - Luigi Bennardis
mvn spring-boot: repackage
java -jar target\demo-spring-boot-h2embHibJmsJta-0.0.1-SNAPSHOT.war
.....HQ221000: live server is starting with configuration HornetQ Configuration(clustered=false,backup=falseHQ221045: libaio is not available, switching the configuration into NIOHQ221043: Adding protocol support COREHQ221003: trying to deploy queue jms.queue.codaPrenotazioneEsamiHQ221007: Server is now liveHQ221001: HornetQ Server version 2.4.5.FINAL (Wild Hornet, 124) [f9175388-bb5f-11e4-88d9-5bae268d51f1] ..........MESSAGGIO PUBBLICATO SULLA CODA codaPrenotazioneEsami :PRE00001|abcd0001|000001MESSAGGIO PUBBLICATO SULLA CODA codaPrenotazioneEsami :PRE00001|abcd0003|000001MESSAGGIO PUBBLICATO SULLA CODA codaPrenotazioneEsami :PRE00001|abcd0005|000001.....
Distribuzione su TOMEE e console di output
Implementazione → HornetQ
Command Line: Run & Console
ROME 27-28 march 2015 - Luigi Bennardis
<!-- TRANSAZIONALITA' ATOMIKOS --><dependency>
<groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jta-atomikos</artifactId>
</dependency>
<spring-boot-starter-jta-atomikos> Definisce la dipendenza alle librerie di Atomikos e auto-configura il container di esecuzione con le funzioni di transazionalità
Maven: dichiarazione delle dipendenze
Implementazione → H2 - Atomikos
ROME 27-28 march 2015 - Luigi Bennardis
@Service @Transactionalpublic class ServicePrenotazioneEsame {
//……public void registraPrenotazione(String codPrenotazione, String codEsame, String matricolaStud) {
//PERSISTENZA DEL RECORD SUL DATABASE this.prenEsameRepo.save(new EntityPrenotazioneEsame(codPrenotazione, codEsame, matricolaStud));
//PUBBLICAZIONE DEL MESSAGGIO SULLA CODA this.jmsTemplate.convertAndSend("codaPrenotazioneEsami", codPrenotazione + "|" + codEsame + "|" +
matricolaStud);
if (codEsame.equals("ROLLBACK_SIMULATO")) { //ECCEZIONE->ROLLBACK TRANSAZIONE throw new RuntimeException("SIMULAZIONE DI ROLLBACK ULTIMA TRANSAZIONE");
} }
@Transactional• Marca in modo dichiarativo i confini della transazionalità • Eccezione fake per eseguire il rollback
Service facade: codifica della direttiva JTA
Implementazione → Atomikos
ROME 27-28 march 2015 - Luigi Bennardis
mvn spring-boot:repackage
java -jar target/demo-spring-boot-h2embHibJmsJta-0.0.1-SNAPSHOT.war
Esecuzione da command line e console
Implementazione → Atomikos
Command Line: Run & Console
.....
.....
No properties path set - looking for transactions.properties in classpath...transactions.properties not found - looking for jta.properties in classpath...Failed to open transactions properties file - using default valuesUsing JTA UserTransaction: com.atomikos.icatch.jta.UserTransactionManager@bb479Using JTA TransactionManager: com.atomikos.icatch.jta.UserTransactionManager@bb479 ..........
MESSAGGIO PUBBLICATO SULLA CODA codaPrenotazioneEsami :PROGRESSIVO MESSAGGIO IN CODA 1|PRE00001|abcd0001|000001MESSAGGIO PUBBLICATO SULLA CODA codaPrenotazioneEsami :PROGRESSIVO MESSAGGIO IN CODA 2|PRE00001|abcd0002|000001SIMULAZIONE DI ROLLBACK ULTIMA TRANSAZIONE
ROME 27-28 march 2015 - Luigi Bennardis
<plugin><groupId>org.cloudfoundry</groupId><artifactId>cf-maven-plugin</artifactId><version>1.0.1</version><configuration>
<server>pivotal-cloud-foundry</server><target>https://api.run.pivotal.io</target><org>luigibennardis.it</org><space>development</space>
<appname>demoSpringBoot</appname><url>demoSpringBoot.cfapps.io</url><memory>1024</memory>
</configuration></plugin>
Maven: plug-in deploy Cloud Foundry
Implementazione → Cloud Foundry
ROME 27-28 march 2015 - Luigi Bennardis
cf:push -Dcf.username=l.bennardis@email.it -Dcf.password=password
.....[INFO] Creating application 'demoSpringBoot'[INFO] Uploading 'C:\development\EclipseWKS\05-demo-spring-boot-h2embHibJmsTransactionalCF\target\demo-spring-boot-h2embHibJmsJtaCf-0.0.1-SNAPSHOT.war'[INFO] Starting application[INFO] -----> Downloaded app package (29M)-----> Java Buildpack Version: v2.7.1 | https://github.com/cloudfoundry/java-buildpack#fee275a-----> Downloading Open Jdk JRE 1.8.0_40 from https://download.run.pivotal.io/openjdk/lucid/x86_64/openjdk-1.8.0_40.tar.gz (2.6s)
Expanding Open Jdk JRE to .java-buildpack/open_jdk_jre (1.3s)-----> -----> Downloading Spring Auto Reconfiguration 1.7.0_RELEASE from https://download.run.pivotal.io/auto-reconfiguration/auto-reconfiguration-1.7.0_RELEASE.jar (0.1s)-----> Uploading droplet (73M)
[INFO] Checking status of application 'demoSpringBoot'[INFO] 0 of 1 instances running (1 starting)[INFO] .....[INFO] 1 of 1 instances running (1 running)
Maven: deploy & console
Implementazione → Cloud Foundry
ROME 27-28 march 2015 - Luigi Bennardis
Gestione dell’istanza
Implementazione → Cloud Foundry
Cloud Foundry: Tail Log - Scale up & Console
ROME 27-28 march 2015 - Luigi Bennardis
Implementazione → Cloud FoundryGestione dell’istanza con il Plug-in di Eclipse
ROME 27-28 march 2015 - Luigi Bennardis
Gestione dell’istanza con il Plug-in di Eclipse
Implementazione → Cloud Foundry
ROME 27-28 march 2015 - Luigi Bennardis
Conclusioni Rapido sviluppo di applicazioni basate su Spring
Vista semplificata dell’ecosistema Spring e delle dipendenze
Auto-configurazione dell’applicazione in base alle librerie dichiarate nel classpath:
H2->datasource+embedding
Hibernate->JPA provider
Progressivo «scale-up» dei componenti «auto-configurati» con versioni più robuste
Soddisfazione di requisiti non funzionali comuni a molti progetti
Copertura di una significativa area del ciclo di vita
Costi ridotti in fase di start-up
Nessuna gestione degli ambienti di run-time (SO/Mware)
Nessuna configurazione server side
Nessun «middleware» installato o da gestire
Flessibilità ed efficienza del deployment
Software design che abilita al Cloud (PAAS)
Altri: Sicurezza, metriche, esternalizzazione di configurazioni
ROME 27-28 march 2015 - Luigi Bennardis
Appendice: JAX-RS (JERSEY) & JSR 330 Soluzione presentata: Spring-Boot -> RESTFull Web Service basato su Spring:
stack completo comprendente MVC, REST, ecc.
annotazioni potenti (Dependency & Context Injection) ma proprietarie Spring.
Evoluzione della soluzione: Spring-Boot -> RESTFull Web Service basato su Jersey & JSR-330
Jersey: framework OS per realizzare Web Services RESTful attraverso API Java JAX-RS
JSR-330: specifica Java per il Contexts and Dependency Injection le piattaforme Java EE.
Iniezione di un Java Bean: @Autowired (Spring) -> @Inject (JSR-330)
Dichiarazione di un Java Bean: @Component(Spring) -> @Named(JSR-330)
ROME 27-28 march 2015 - Luigi Bennardis
@SpringBootApplicationpublic class Application {
@Namedpublic static class JerseyConfig extends ResourceConfig {
public JerseyConfig() { this.register(Controller.class);
} } public static void main(String[] args) {
SpringApplication.run(Application.class, args); }
}
@NamedDichiarazione di iniezione di un Java Bean nel contesto in fase di scansione del classpath
Classe Java per eseguire Spring-Boot con Jersey
Implementazione JAX-RS: JERSEY- JSR330
ROME 27-28 march 2015 - Luigi Bennardis
@Named@Transactionalpublic class ServicePrenotazioneEsame {
@Injectprivate JmsTemplate jmsTemplate;
@PersistenceContextprivate EntityManager entityManager;
public void registraPrenotazione(String codPrenotazione, String codEsame, String matricolaStud) {
//PERSISTENZA DATI SUL DATABASE this.entityManager.persist(new EntityPrenotazioneEsame(codPrenotazione, codEsame, matricolaStud));
//PUBBLICAZIONE MESSAGGIO SULA CODA this.jmsTemplate.convertAndSend("codaPrenotazioneEsami","PROGRESSIVO MESSAGGIO IN CODA "+
counter.incrementAndGet( )+ "|" + codPrenotazione + "|" + codEsame + "|" + matricolaStud);
@InjectPunto di iniezione di un Java Bean: non sono necessari set/get
Service Facade: annotazioni JSR-330
Implementazione JAX-RS: JERSEY- JSR330
ROME 27-28 march 2015 - Luigi Bennardis
@Named@Path("/prenotaEsameTest") @Produces(MediaType.TEXT_HTML) public class Controller {
@Injectprivate ServicePrenotazioneEsame service;
@GET @Path("/infoPrenota") public Response get(@QueryParam("codiceEsame") String codiceEsame,
@QueryParam("matricolaStudente") String matricolaStudente) { //…………try {
service.registraPrenotazione("aa00099",codiceEsame, matricolaStudente); esitoPrenotazione = "ESEGUITA";
} //………… }
@GETMetodo Get della request HTTP
@PathDefinisce la corrispondenza della risorsa (sub-risorsa) alla classe (metodo)
Controller REST: annotazioni Jersey
Implementazione JAX-RS: JERSEY- JSR330
ROME 27-28 march 2015 - Luigi Bennardis
Link
https://github.com/lbennardis/Codemotion15SpringBoot (codice sorgente)
http://projects.spring.io/spring-boot/ (Spring-Boot)
http://tomee.apache.org/ (Tomcat EE)
http://cloudfoundry.org/index.html (Cloud Foundry)
https://jersey.java.net/ (Jersey)
https://jcp.org/en/jsr/detail?id=330 (JSR-330)
https://jcp.org/en/jsr/detail?id=250 (JSR-250)
ROME 27-28 march 2015 - Luigi Bennardis
Leave your feedback on Joind.in!
https://joind.in/event/view/3347