Web-Oriented Architecture -WOA-

Web-Oriented Architecture -WOA-

History

Rich Client Platform -RCP-

New York City Penitentiary case study ⤳ run New_York_City_Penitentiary_Java_SE application

Three-tier architecture

Three-tier architecture cont'd

Three-tier Java application (middleware)

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

Component models

Application Programming Interfaces -APIs-

Object versus component versus service

Java EE as middleware (e.g., GlassFish)

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

GlassFish ⤳ domain creation*

Example (domain creation)

asadmin> create-domain --user barbier --adminport 4850 --savemasterpassword=true --savelogin=true FranckBarbier

List of domains

*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)

GlassFish ⤳ resource creation

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

Java EE technical services

Timer services in Enterprise JavaBeans

@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"));
…

Designing (business) Web Services in Java

*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

Microservice design pattern ⤳ step 1 JPA (overview )

@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;
    }
    …

Microservice design pattern ⤳ step 2 Spring (overview )

@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();
}

Microservice design pattern ⤳ step 3 Spring (overview )

@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);
}

Microservice design pattern ⤳ step 4 Spring (overview )

@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); }

Microservice consumption ⤳ POST Spring

Hypermedia as the Engine of Application State -HATEOAS-

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

HATEOAS ⤳ Spring (tutorial )

// 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();
            }
            …

HATEOAS ⤳ Spring cont'd

// 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;
            }

HATEOAS ⤳ “business-logic” navigation links

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"
                        }
                }
        }

© BarbierDarnal.com