Web-Oriented Architecture -WOA-

Web-Oriented Architecture -WOA-

History

Component models (samples)

Application Programming Interfaces (APIs)

Client/server computing (illustration)

Three-tier architecture

Three-tier architecture cont'd

Three-tier Java application (middleware)

Microservices architecture (SQL)

Microservices architecture (NoSQL)

Service ⤳ Software as a Service -SaaS-

Object versus component versus service

SOA/WOA

Technical services (middleware)

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

Business layer

Business services (applications)

Business microservices design: persistence with Java Persistence API -JPA-

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

Business microservices design: persistence (Spring)

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

Business micro-service design: service (Spring) 1/2

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

Business micro-service design: service (Spring) 2/2

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

Business micro-service design: configuration (Spring)

application.properties file

spring.jpa.hibernate.ddl-auto=none
spring.datasource.url=jdbc:derby:memory:local;create=true
server.servlet.contextPath=/NYCP/API

NewYorkCityPenitentiary_application.java file

@org.springframework.boot.autoconfigure.SpringBootApplication
public class NewYorkCityPenitentiary_application {
    public static void main(String[] args) {
        org.springframework.boot.SpringApplication.run(NewYorkCityPenitentiary_application.class, args);
    }
}

New_York_City_Penitentiary_Spring.zip

Business micro-service design: POST (Spring)

Hypermedia as the Engine of Application State -HATEOAS-

The Web Services W3 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), RESTful-oriented architecture promotes a dynamical approach, which is HATEOAS.

Use cases, advantages, and disadvantages here

HATEOAS in Spring (see also tutorial)

// Inheriting 'RepresentationModel' provides an 'add' method to create "business-logic" RESTful 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 in 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;
    }

Hypermedia as the Engine of Application State (HATEOAS): "business-logic" RESTful 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"
                }
        }
}

Business analysis

RPA with BPMN

Payment case study (1/4)

Payment case study (2/4)

Payment case study (3/4)

Payment case study (4/4)

RESTful Web Service consumption (connection)

public static double Convert(Currencies fromCurrency, Currencies toCurrency, double amount)
    throws java.net.MalformedURLException, java.io.IOException {
    java.net.URL url = new java.net.URL("http://openexchangerates.org/api/latest.json" + "?app_id=" + _License_key);
    java.net.URLConnection connection = (java.net.URLConnection) url.openConnection();
    if (connection != null) {
// No specific configuration data so 'null':
        javax.json.stream.JsonParserFactory factory = javax.json.Json.createParserFactory(null);
        javax.json.stream.JsonParser parser = factory.createParser(connection.getInputStream());
        …

Currency_conversion.Java.zip

RESTful Web Service consumption (processing data)

while (parser.hasNext()) {
    javax.json.stream.JsonParser.Event event = parser.next();
    if (event == javax.json.stream.JsonParser.Event.KEY_NAME && parser.getString().equals(toCurrency.currency)) {
        while (parser.hasNext()) {
            event = parser.next();
            if (event == javax.json.stream.JsonParser.Event.VALUE_NUMBER) {
                amount *= parser.getBigDecimal().doubleValue(); // Conversion rate acquisition (free), but direct conversion is with charge!
                break;
            }
        }
    }
}

Currency_conversion.Java.zip

JavaScript Object Notation (JSON) data

{
    "success":true,
    "timestamp":1656062943,
    "base":"EUR",
    "date":"2022-06-24",
    "rates":{"AED":3.874208,"AFN":94.22818,"ALL":119.759709,"AMD":434.685387,…}
}

Service deny (security issue)

SOAP Web Service specification (URL?WSDL)

<wsdl:documentation> Currency Server - An exchange rate information and currency conversion Web service.
</wsdl:documentation>
…
<s:element name="Convert">
    <s:complexType>
        <s:sequence>
            <s:element minOccurs="0" maxOccurs="1" name="licenseKey" type="s:string"/>
            <s:element minOccurs="0" maxOccurs="1" name="fromCurrency" type="s:string"/>
            <s:element minOccurs="0" maxOccurs="1" name="toCurrency" type="s:string"/>
            <s:element minOccurs="1" maxOccurs="1" name="amount" type="s:double"/>
            <s:element minOccurs="1" maxOccurs="1" name="rounding" type="s:boolean"/>
            <s:element minOccurs="0" maxOccurs="1" name="format" type="s:string"/>
            <s:element minOccurs="1" maxOccurs="1" name="returnRate" type="tns:curncsrvReturnRate"/>
            <s:element minOccurs="0" maxOccurs="1" name="time" type="s:string"/>
            <s:element minOccurs="0" maxOccurs="1" name="type" type="s:string"/>
        </s:sequence>
    </s:complexType>
</s:element>

SOAP Web Service consumption* in Java (URL)

A SOAP Web Service requires a Web Services Description Language (WSDL) specification.

// Location of the WSDL specification:
@javax.xml.ws.WebServiceRef(wsdlLocation = "META-INF/wsdl/fx.currencysystem.com/webservices/CurrencyServer5.asmx.wsdl")
com.currencysystem.webservices.currencyserver.CurrencyServer service;
…
com.currencysystem.webservices.currencyserver.CurrencyServerSoap port = service.getCurrencyServerSoap12();
Object o = port.convert(licenseKey, fromCurrency, toCurrency, amount, rounding, format, returnRate, time, type);

*Apache CXF may automatically generate client components (consumers) in Java, JavaScript or other languages from WSDL.

SOAP Web Service consumption* in Node.js (URL)

const soap = require('soap');

soap.createClientAsync("https://fx.currencysystem.com/webservices/CurrencyServer5.asmx?wsdl").then((client: any) => {
    // console.log(JSON.stringify(client.describe()));
    const ActiveCurrencies = client['ActiveCurrencies'];
    ActiveCurrencies(null, (err: any, result: any, envelope: any, header: any) => {
        console.log("Result: " + JSON.stringify(result));
    });
    const Convert = client['Convert'];
    Convert({
        fromCurrency: "EUR",
        toCurrency: "MAD",
        amount: 1,
        rounding: true,
        returnRate: "curncsrvReturnRateString"
    }, (err: any, result: any) => {
        console.log("Result: " + result.data);
    });
});

Web Services in Java

*RESTful Web Services have gained leadership because of their wide take-up by Google, Amazon, Facebook, etc. RESTful Web Services single out the idea of “resource” as the key means to retrieve data from Web places supporting exposed Web Services. While RESTful Web Services may be described with the help of WSDL, WADL (Web Application Description Language) is the preferred support.

Enterprise Service Bus (ESB)

An ESB (e.g., Apigee) eases the discovering and access to services in a business perspective. It aims at including service interoperability both from a syntactical and semantic viewpoint.

Cloud computing

“The key objective of cloud computing is the transparent access to computing resources without the need for an infrastructure and its management. For example, a chat application intensively requires message queues, their installation, their configuration, their administration and their use through programs.”

Cloud computing providers

Private, public or hybrid cloud computing platforms?

Messaging

Intuitive messaging versus broker-based messaging (right-hand side)

Message brokers

JMS that is fully part of Java EE:

JMS, managed resources

JMS, communication modes

*Scalability issues lead to have many instances of a listener type.

JMS, point-to-point

JMS, publish-subscribe

© Franck Barbier