New York City Penitentiary case study
☛
⤳ run New_York_City_Penitentiary_Java_SE
application
New York City Penitentiary case study
☛
⤳ run New_York_City_Penitentiary_Spring
application
New York City Penitentiary case study
☛
⤳ run New_York_City_Penitentiary_Java_EE
application
Resource acquired and released by components, services, applications… are managed in an administrative way to share resources and optimize usages
Change to Java 8 before launching asadmin
(Windows PowerShell)
echo "Java home: $env:JAVA_HOME"
$env:PATH = "C:\Program Files\Java\jdk-1.8\bin;$env:PATH"
echo "PATH: $env:PATH"
cd C:\Users\franc\Documents\NetBeansProjects\glassfish-5.1.0\glassfish5\bin
Start-Process ".\asadmin.bat"
Change to Java 8 before launching asadmin
(macOS)
export JAVA_HOME=`/usr/libexec/java_home -v 1.8.0_333`
cd /Users/FranckBarbier/NetBeansProjects/glassfish5/bin
./asadmin
Example (domain creation)
asadmin> create-domain --user barbier --adminport 4850 --savemasterpassword=true --savelogin=true FranckBarbier
List of domains
domain1
, admin port 4848 (admin/adminadmin)FranckBarbier
, admin port 4850 (barbier/<typed password> for admin and master passwords)
.asadminpass
(Windows: C:\Users\franc\Documents
)*To mount extra JAR libraries on
GlassFish related files have to be added to
<GlassFish
installation directory>/glassfish/domains/domain1/lib/ext
(domain1
may be replaced
by FranckBarbier
for instance)
Example of JDBC resource creation (JavaDB)
asadmin> start-domain domain1
asadmin> list-jdbc-connection-pools
asadmin> delete-jdbc-connection-pool New_York_City_Penitentiary_database_pool
asadmin> create-jdbc-connection-pool --help
asadmin> create-jdbc-connection-pool --datasourceclassname org.apache.derby.jdbc.ClientDataSource --restype javax.sql.DataSource --driverclassname=org.apache.derby.jdbc.ClientDriver --property user=FranckBarbier:password=FranckBarbier:databasename=New_York_City_Penitentiary_database:servername=localhost:portnumber=1527 New_York_City_Penitentiary_database_pool
# Database server must run:
asadmin> ping-connection-pool New_York_City_Penitentiary_database_pool
asadmin> list-jdbc-resources
asadmin> delete-jdbc-resource jdbc/New_York_City_Penitentiary
asadmin> create-jdbc-resource --connectionpoolid New_York_City_Penitentiary_database_pool jdbc/New_York_City_Penitentiary
asadmin> stop-domain domain1
Example of persistence.xml
file
<persistence-unit name="NYCP_persistence_unit" transaction-type="JTA">
<jta-data-source>jdbc/New_York_City_Penitentiary</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties/>
</persistence-unit>
Example of JDBC resource creation (Oracle)
# Beforehand, put 'ojdbc8-21.7.0.0.jar'in <GlassFish installation directory>/glassfish/domains/domain1/lib/ext:
create-jdbc-connection-pool --datasourceclassname oracle.jdbc.pool.OracleDataSource --restype javax.sql.DataSource --property user=<USER>password:=<PASSWORD>:url="jdbc\\:oracle\\:thin\\:@my_machine.BarbierDarnal.com\\:1521\\:my_access" New_York_City_Penitentiary_database_pool
javax.ejb.TimerService
) in Enterprise JavaBeans™ can be requested by components
beyond the dependency on clocks of physical machines or distributed
Java Virtual Machines -JVMs-
@javax.annotation.Resource
private javax.ejb.TimerService _timer_service = null;
…
// A timer object is created for a specific usage, e.g., after 1000 ms, only one time, the “my_business_method” Java method is called:
assert(_timer_service != null);
_timer_service.createSingleActionTimer(1000L, new javax.ejb.TimerConfig("Data passed to timed task", false));
…
// The timed task:
@javax.ejb.Timeout
public void my_business_method(javax.ejb.Timer timer) {
String s = (String)timer.getInfo();
assert(s != null && s.equals("Data passed to timed task"));
…
javax.ws.rs
package:
characterization
within “The Java EE Tutorial” ☛
*REST Web Services have gained leadership because of their wide take-up by Google, Amazon or Facebook. REST Web Services single out the idea of “resource” as the key means to retrieve data from Web places supporting exposed Web Services. While REST Web Services may be described with the help of WSDL, Web Application Description Language -WADL- ☛ is the preferred support
@javax.persistence.Entity
@javax.persistence.Table(name = "PRISONER")
@javax.persistence.NamedNativeQuery(name = "Prisoner.Under_remand_SQL", query = "SELECT * FROM Prisoner WHERE prison_file_number NOT IN (SELECT prison_file_number FROM Conviction)")
@javax.persistence.NamedQueries({
@javax.persistence.NamedQuery(name = "Prisoner.All_JPQL", query = "SELECT p FROM Prisoner p"),
@javax.persistence.NamedQuery(name = "Prisoner.Under_remand_JPQL", query = "SELECT p FROM Prisoner p WHERE p._conviction IS EMPTY")
})
public class Prisoner implements java.io.Serializable {
private static final long serialVersionUID = 1L;
@javax.persistence.Id
@javax.persistence.Basic(optional = false)
@javax.validation.constraints.NotNull
@javax.validation.constraints.Size(min = 1, max = 10)
@javax.persistence.Column(name = "PRISON_FILE_NUMBER")
private String _prison_file_number;
public String get_prison_file_number() {
return _prison_file_number;
}
…
@org.springframework.stereotype.Repository
public interface PrisonerDao extends org.springframework.data.jpa.repository.JpaRepository<Prisoner, String> {
@org.springframework.data.jpa.repository.Query(value = "SELECT * FROM Prisoner WHERE prison_file_number NOT IN (SELECT prison_file_number FROM Conviction)", nativeQuery = true)
java.util.List<Prisoner> under_remand();
}
@org.springframework.stereotype.Service
public interface JSON_service {
public enum QUERY {
ALL_CRIMINAL_CASES, ALL_JUDICIAL_DECISIONS, ALL_MOTIVES, ALL_OFFENSES, ALL_PRISONERS, UNDER_REMAND_PRISONERS
};
String to_JSON(QUERY type);
}
@org.springframework.web.bind.annotation.RestController
public class PrisonerCRUD implements JSON_service {
@org.springframework.beans.factory.annotation.Autowired
private PrisonerDao _prisonerDao;
@Override
public String to_JSON(QUERY type) {
java.util.List<Prisoner> prisoners = type == QUERY.ALL_PRISONERS ? _prisonerDao.findAll() : type == QUERY.UNDER_REMAND_PRISONERS ? _prisonerDao.under_remand() : new java.util.LinkedList<>();
javax.json.JsonArrayBuilder _prisoners = javax.json.Json.createArrayBuilder();
for (Prisoner prisoner : prisoners) {
javax.json.JsonObjectBuilder builder = javax.json.Json.createObjectBuilder();
builder.add("GIVEN_NAME", prisoner.get_given_name());
builder.add("SURNAME", prisoner.get_surname());
_prisoners.add(builder.build());
}
return _prisoners.build().toString();
}
// http://localhost:8080/NYCP/API/prisoners
@org.springframework.web.bind.annotation.GetMapping(value = "/prisoners")
public String all() { return to_JSON(QUERY.ALL_PRISONERS); }
POST
SpringContent-type
'application/x-www-form-urlencoded'
// curl -X POST -d 'motive_number=02&motive_label=assault and battery' http://localhost:8080/NYCP/API/motives/new
@org.springframework.web.bind.annotation.PostMapping(value = "/new") // <=> '@RequestMapping(method = RequestMethod.POST)'
public void post_(@org.springframework.web.bind.annotation.RequestParam java.util.Map<String, String> query) {
Motive motive = new Motive();
motive.set_motive_number(query.get("motive_number"));
motive.set_motive_label(query.get("motive_label"));
_motiveDao.save(motive);
}
Content-type
'application/json'
// curl -X POST -H "Content-Type: application/json" -d '{"_motive_number":"02", "_motive_label":"assault and battery"}' http://localhost:8080/NYCP/API/motives
@org.springframework.web.bind.annotation.PostMapping(value = "", // <=> '@RequestMapping(method = RequestMethod.POST)'
consumes = org.springframework.http.MediaType.APPLICATION_JSON_VALUE)
public void post(@org.springframework.web.bind.annotation.RequestBody Motive motive) {
_motiveDao.save(motive);
…
}
The Web Services W3C technology generates the need for API discoverability that may leverage, for instance, Web Services semantic composition
While prior middleware or Web Services technologies (e.g., CORBA, SOAP) single out entry points as fixed interfaces (e.g., in Interface Description Language -IDL- for CORBA, WSDL for SOAP), REST-oriented architecture promotes a dynamical approach, which is HATEOAS
Use cases, advantages, and disadvantages ☛
// Inheriting 'RepresentationModel' provides an 'add' method to create "business-logic" navigation links:
public class Motive extends org.springframework.hateoas.RepresentationModel<Motive> implements java.io.Serializable { …
@org.springframework.web.bind.annotation.RestController
@org.springframework.web.bind.annotation.RequestMapping(value = "/motives")
public class MotiveCRUD implements JSON_service {
@org.springframework.beans.factory.annotation.Autowired
private MotiveDao _motiveDao;
…
@org.springframework.web.bind.annotation.GetMapping(value = "/{motive_number}")
public String get(@org.springframework.web.bind.annotation.PathVariable String motive_number) {
java.util.Optional<Motive> motive = _motiveDao.findById(motive_number);
javax.json.JsonObjectBuilder builder = javax.json.Json.createObjectBuilder();
if (motive.isPresent())
builder.add("MOTIVE_LABEL", motive.get().get_motive_label());
return builder.build().toString();
}
…
// curl -X POST -H "Content-Type: application/json" -d '{"_motive_number":"02", "_motive_label":"assault and battery"}' http://localhost:8080/NYCP/API/motives
@org.springframework.web.bind.annotation.PostMapping(value = "", // <=> '@RequestMapping(method = RequestMethod.POST)'
consumes = org.springframework.http.MediaType.APPLICATION_JSON_VALUE)
public org.springframework.hateoas.RepresentationModel<Motive> post(@org.springframework.web.bind.annotation.RequestBody Motive motive) {
_motiveDao.save(motive);
// 'linkTo' inspects the controller class and obtains its root mapping, e.g., http://localhost:8080/NYCP/API/motives
// 'slash' adds 'motive_number' as the path variable of the link
// finally, 'withSelfRel' qualifies the relation as a self-link
org.springframework.hateoas.Link link
= org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo(MotiveCRUD.class).slash(motive.get_motive_number()).withSelfRel();
// System.out.println(link.toUri().toString()); // e.g., http://localhost:8080/NYCP/API/motives/02
motive.add(link);
return motive;
}
curl -X POST -H "Content-Type: application/json" -d '{"_motive_number":"02", "_motive_label":"assault and battery"}'
\ http://localhost:8080/NYCP/API/motives
{
"_motive_number":"02",
"_motive_label":"assault and battery",
"_links":
{
"self":
{
"href":"http://localhost:8080/NYCP/API/motives/02"
}
}
}