- Free open source tool to test SOAP webservices
- Download soapui (free version)
- Open SOAPUI
- Maven related errors
- goto
.m2folder
- goto
- Run
mvn clean mvn installshould install all dependencies afresh- Run Maven > Update Project in Eclipse
- Download Java Web Services
- Order for only RESTFul web services
- Software Setup
- Install everything except SOAPUI
- XML and XML Schema Definition Crash Course (optional)
- Apache CXF
- Section 16 to the end
- Maven related issues
- Goto
.m2folder/directory - Delete the
repositoryfolder - Do
mvn clean install - Right click on project > Maven > Update Project
- Goto
- Search for Jaxb maven dependency (was part of JDK prior to 10)
- It is part of Java EE
-
Take JAXB API latest version
<dependency> <groupId>javax.xml</groupId> <artifactId>jaxb-api</artifactId> <version>2.1</version> </dependency>
-
- It is part of Java EE
-
Always up to date
-
Spring Boot upgrade to latest
-
Apache CXF jaxws/jaxrs spring boot maven
-
cxf-codegen-plugin (latest version is preferred)
-
Maven > Update Project
-
application.properties
server.servlet.context-path=/wsdlfirstws
-
-
Library incompabilities
- Delete
.m2/repository
- Delete
- Refresh by refering to lectures once a week
- Topics:
- What are web services?
- Two types of web services
- Java Standards for the types
- What?
- Web services are client server/ consumer provider apps that communicate over the network through HTTP protocol and exchange messages/data in various formats
- Advantages:
- Interoperability: Software apps developed in different programming languages can communicate with each other (even if running on different platforms)
- Loosely Coupled: Two or more apps can communicate in loosely coupled fashion
- Any app can replace the other if the web services standard is maintained
- Extensibility: We can integrate different apps easily
- Web service producers can expose services, and consumers can come up with logic to consume the services
- Mashups: Mashup apps can consume web services from multiple applications
- Types:
- SOAP
- XML based messages over HTTP POST request
- RESTFul:
- All HTTP methods can be used
- Multiple data formats are supported
- SOAP
- Tools for SOAP and RESTFul web services:
- JAX-WS: SOAP web services API
- JAX-RS: RESTFul web services API
- Java API for RESTFul web services
- Topics:
- What is SOA?
- Collection of architectural principles to design and implement software apps in such a way that they are composed of several software services that have simple well defined interfaces and that can use each other in a loosely coupled manner
- Maintained by W3C and OASIS (architectural principles)
- We can use them in Web services
- SOA has two roles
- Consumer
- Provider
- Can be consumer of another service
- Example:
- SOA definition:
- Service: Implementation of business logic that operates in independence of state of another service
- Appointment management consumes Patient service and Doctor Service
- Doctor service consumes Clinical service
- Clinical service consumes Patient service
- Patient service consumes Bed management service
- SOA definition:
- Contract should be intect
- SOAP: WSDL
- REST: WADL
- SOA data format:
- XML: It has data + metadata (what to do with that data)
- Who uses SOA?
- Why SOA?
- Why Web Services? Implements SOA principles
- What is SOA?
- Advantages of SOA:
- Platform independence
- Focussed developer roles (per service)
- Loosely coupled
- Reusability (google mail, drive, docs)
- Cost reduction
- Scalability
- If user base grows, we can deploy the services in multiple servers
- Availability
- More reliable because a server going down does not bring down services
- Interoperability
- Web services are consumer and provider applications that can be written in multiple languages running on different platforms which can communicate with each other
- HTTP
- XML
- Advantages:
- Interoperability
- Loosely Coupled
- Extensibility
- Mashups
- Two types of Web services:
- SOAP
- JAX-WS
- REST
- JAX-RS
- SOAP
- SOA: Architectural principles
- Service: Implementation of business logic that operates on its own
- Web services is one of ways in which SOA can be implemented
- XML is usually used in two places
- For configuration
- CXF uses spring configuration
- For exchanging data
- SOAP and REST
- For configuration
- Topics
- How to construct XML document
- What is well formed XML document
- Contract for XML using XSD (XML Schema Definition)
- Namespaces
- eXtensible Markup Language
- We can construct our own markup based on business requirement
- HTML provides special meaning to it's elements
- XML does not have pre-defined set of elements
- Example:
OrderMLOrderIDLineItemsShippingAddress
- Example:
NewsMLHeadlinesPoliticsSports
- Example:
- Advantages:
-
Custom Markup
<Order> <OrderId>123</OrderId> <ShippingInfo>...</ShippingInfo> ... </Order> -
It carries both data and meta-data (tells what is the information for)
-
Amazon Web app - xml -> Amazon Shipping
OrderId ShippingInfo - what to do with it (where to send)
-
-
Well-Formedness rules - clean xml is only allowed or else rejected
-
Validation - schema files validate the xmls
-
- Three places it is mostly used
- Data exchange
- XML can be used for data and meta-data
- Configuration
- web.xml
- server.xml
- pom.xml
- build.xml
- Save and/or manipulate and present data
- Client sent request to Portal which saves to repository
- Portal fetched xml from repository and transforms into HTML and sends it to client
- Data exchange
- XSD is grammar or blueprint for xml
- Elements
- Attributes
- Namespaces
- Order
- Number of Occurrences
- Restrictions (values)
- If XML follows XSD, then it is valid
- xsd file is also an xml file with .xsd extension
- Elements in xsd are provided by W3C
- Example: order.xml and order.xsd
- Why and where?
- It is a contract between applications
- Example: Employee management software
- xml configuration file defines to the management software where the database is and how to use it
- management software validates the config using xsd
- xml configuration file defines to the management software where the database is and how to use it
-
Uniquely identify XML components
-
Schema:
targetNamespace- for all elements in order- Use unique url as namespace
http://www.amazon.com/order
- Use unique url as namespace
prefix- represents namespacexmlns:amz="http://www.amazon.com/order"xmlns:ebay="http://www.ebay.com/order"
-
xml doc:
<order xmlns:amz="http://www.amazon.com/order"> <amz:lineItem/> <amz:shippingAddress/> ... <order xmlns:ebay="http://www.ebay.com/order"> <ebay:lineitem/> <ebay:shippingAddress/> ... -
Namespace is similar to package in Java
- In built types and own complex and simple types
- Example: Hospital management site
- Patient billing application
- Patient checkout
- Patient billing
- Insurance
- Patient Clinical application
- x ray
- blood test
- Patient data is exchanged between apps
- Patient billing application
- Requirements:
- Patient data
- Name
- Age
- DOB
- Gender
- Phone
- Patient data
-
Open Eclipse
-
File > New > Others > Project
-
Name; PatientXML
-
Right click on project > New > Other > XML > XML Schema File > patient.xsd
<schema ...> <!-- root element --> </schema>-
xmlns: namespace- w3c namespace: defines all elements that can be used in a schema file
-
targetNamespace: any xml should comply with this namespacehttp://www.bharaththippireddy.com/Patient- Domain name + business object
-
xmlns:tns: prefix for our namespace-
Used to refer to elements in this namespace
http://www.bharaththippireddy.com/Patient
-
-
-
-
Code
<element name="patient" type="tns:Patient"/> <!-- case sensitive --> <complexType name="Patient"> <sequence> <!-- gives order of elements --> <element name="id" type="int" /> <!-- int defined by w3c --> <element name="name" type="string" /> <element name="age" type="int" /> <element name="dob" type="date" /> <element name="email" type="string" /> <element name="gender" type="string" /> <element name="phone" type="string" /> </sequence> </complexType> -
xml: Right click on project > new > XML > Patient.xml
- Create XML file from a XML schema file
- Select Project > Patient.xsd
- id: 1
- name: bharath
- age 33
- dob: ...
- email: [email protected]
- gender: M
- Uses target namespace defined in xsd
xsd:schemaLocation: namespace followed by schema filename
-
Right click on xml and validate
-
How to use simple types and restrict values
<element name="id" type="tns:ID" /> <element name="name" type="tns:String15Chars" /> <element name="gender" type="tns:Gender" /> <simpleType name="ID"> <restriction base="int"> <pattern value="[0-9]*"></pattern> </restriction> </simpleType> <simpleType name="String15Chars"> <retstriction base="string"> <maxLength balue="15" /> </restriction> </simpleType> <simpleType name="Gender"> <restriction base="string"> <enumeration value="M" /> <enumeration value="F" /> </restriction> </simpleType> -
Re-generate Patient.xml
- Give invalid values and check
-
Adding complex type with complex type
-
Controlling order
<complexType name="Patient"> ... <element name="payment" type="tns:PaymentType" /> </complexType> <complextType name="PaymentType"> <choice> <element name="cash" type="int" /> <element name="insurance" type="tns:Insurance" /> </choice> </complexType> <complexType name="Insurance"> <all> <!-- all should appear but order does not matter --> <element name="provider" type="string" /> <element name="limit" type="int" /> </all> </complexType> -
Re-generate xml
-
Use
insurance<tns:payment> <tns:insurance> <tns:provider>Blue Cross</tns:provider> <tns:limit>1000</tns:limit> </tns:insurance> </tns:payment>
-
-
How many times an element should occur
<element name="id" type="tns:ID" maxOccurs="2" /> -
Unbounded
<element name="email" type="string" minOccurs="0" maxOccurs="unbounded" />
elementFormDefault-qualified- Any xml document following the schema must be qualified (
tnsin this case) unqualified-tnscan be removed
- Any xml document following the schema must be qualified (
-
Attributes
<complextType name="Patent"> ... <attribute name="id" type="tns:ID" /> </complexType> -
Patient.xml
<tns:patient ... id="123"> <!-- remove id element --> ... </tns:patient>
- XML: eXtensible Markup Language
- Custom elements and tags
- Data and meta data
- Config file or exchange info
- Well-formedness rules
- xsd can be used to validate xml
- xsd is contract between xml provider and consumer
- xml document
- In-built type, simple types, complex type
- Namespaces
- Restrictions
- Order of elements
- Number of times an element can occur
- Attributes
- Advantages and disadvantages
- Building blocks
- SOAP
- WSDL
- HTTP
-
Communication independent of language or platform app is running on
-
Web services is implementation
- loosely coupled and easy communication running on different platforms running different languages
- English to this world is what web services are to computer world. A common communication medium
-
Web apps were using http and html
- Web services work with http and xml
- xml can be read by any application and can be converted to langauge specific data types
- Web services work with http and xml
-
Example: Windows/.Net communicating with Linux/Java
- Linux/Java communicates with legacy Mainframe services
-
Data and metadata
<customerName>Bharath</customerName> <!-- customerName is meta data and Bharath is data --> customer.name = "Bharath"; -
Example: Hospital management system
- Patient Services
- Clinical Services
- Billing Services
- Insurance Services (outsite hospital)
- Advantages
- Platform independent
- Apps running in heterogenous environments can communicate
- HTTP - transport independent
- XML - Data independent (data + metadata)
- Apps running in heterogenous environments can communicate
- Application tailoring/customization
- Customers can customize and extend their products by re-using web services given to them
- Legacy applications can be used if they support xml and http
- A layer of web services can be built as a wrapper
- WS opens door from new revenue/profit channels
- ws can be offered as a payed service for clients
- Firewalls like web services
- Port 80 is usually not blocked
- Platform independent
- Cons
- Ambiguous Web Services Standards
- Different companies
- Performance Impact due to Serialization and De-Serialization (SOAP usually)
- REST is light weight
- Ambiguous Web Services Standards
- When?
- Formal contract is required between client and server
- WSDL
- What is provided and how it is provided
- WSDL
- Architecture has to address a lot of non functional requirements (SOAP has standards and out of the box - CXF ... provide implementation with minimum code)
- Security
- Transaction management
- ...
- WS needs reliable asynchronous processing
- SOAP - Out of box - just configuration
- Formal contract is required between client and server
- Simple Object Access Protocol
-
Spec from w3c
- Current version: 1.2
-
Rules come in an xml doc
<soap:Envelope> <!-- root element in namespace --> <soap:header/> <!-- meta info --> <soap:Body> <!-- data --> <creditcard> ... </creditcard> </soap:Body> </soap:Envelope>-
Example: Bank integration
- Bank exposes web service
- Credit card info is accepted
- Response is successful or failure
- Bank exposes web service
-
If transaction fails
<soap:Body> <soap:Fault> <!-- optional, child of body, error info --> <soap:code>soap:Server</soap:code> <!-- client side or server side error --> <soap:Reason> <!-- What is the exact reason --> <soap:text> Card Expired </soap:text> </soap:Reason> </soap:Fault> </soap:Body>- Exceptions are converted to SOAP faults
-
SOAP header
<soap:Header> <!-- meta info - security, ... standard - out of box implementation --> <wsse:Security> <wsse:UsernameToken> <wsse:Username>... <wsse:Password>... </wsse:UsernameToken> </wsse:Security> </soap:Header>
-
-
- WSDL - Web Services Description Language
- Contract
- *.wsdl
- Contract
- Two things it describes:
- What the web service provides
- How it provides it and how you can consume it
- What request should consumer send
- What response should go back
- WSDL is divided into two portions
- Abstract portion
- What is provided
- Elements
- types
- Has all the datatypes which we need to exchange information - (XML Schema)
- messages - like parameters and return types
- Use types to define messages
- operation - like methods in java
- Operation name
- Request message
- Response message
- porttype - it is a container of all the operations that web service is providing
- types
- Elements
- What is provided
- Physical portion
- How to consume the web service from the consumer
- Elements
- binding - how consumer can consume the service and how provider is going to send the response back
- document-literal wrapped (CXF validates)
- It defines binding between abstract section and physical section
- service - how to access the web service
- URL - replaced dynamically by apache CXF
- Port
- binding - how consumer can consume the service and how provider is going to send the response back
- Elements
- How to consume the web service from the consumer
- Abstract portion
-
SOAP binding styles
<binding style="document/literal">- Three things impacted depending on style
- How the SOAP payload looks like
- Whether the SOAP body will be validated against the schema is determined
- Whether the operation name (method) invoked is part of the SOAP body or not
- Three things impacted depending on style
-
Search for "which wsdl style should I use"
- RPC/encoded - can be used for both RPC and JAX-WS
- Type info in included in request
- Operation name appears in request (CXF can easily dispatch)
- Weeknesses: overhead
- Not ws-i compliant
- Cannot be used across platforms
- Request cannot be validated against the schema (operation name is matched with operation key)
- Not ws-i compliant
- RPC/literal - wsdl is same as RPC/encoded (but style)
- request does not have encoding information - no type
- Strength: operation name appears, type info is eliminated (performance)
- WS-I compliant
- Weeknesses: Cannot be validated against schema in wsdl (message is not from types section)
- Document/encoded
- Not WS-I compliant - skipped
- Document/literal
- Improves over RPC styles
- Compliant with WS-I
- Types are defined in
<types>section- Inputs are defined here
- Inputs are referred in message
- Body will directly have the inputs
- Strengths:
- No encoding info
- We can validate the soap body against schema defined in types section
- WS-I compliant but has restrictions
- Weeknesses
- More complicated - schema, types
- But can be overcome since tools are available to generate WSDL from java files
- Operation name is gone
- CXF has tough time figuring out the operation
- Not WS-I compliant because only one child element is allowed in body but has multiple (no root element) - style is still document/literal
- More complicated - schema, types
- Document/literal wrapped - most used
- Input parameter types are wrapped inside complex types - root element for schema
- Name of the element is the name of the operation itself (key)
- Element is used inside the message
- Element is used inside the operation
- Strengths:
- data is wrapped inside operation
- No encoding information
- We can validate the entire soap body against the schema definition
- Method name is used in request - CXF can use it to dispatch - the name matches the operation name in Java or .Net
- WS-I compliant
- Weeknesses:
- Complicated WSDL
- Overloaded methods cannot be used - two elements must be defined with same name but not allowed
- Input parameter types are wrapped inside complex types - root element for schema
- RPC/encoded - can be used for both RPC and JAX-WS
-
Document describes when to use which style and when not to use it
- SOAP uses HTTP and XML
- Advantages
- Platform independence
- Extend application/ customize application
- We can integrate legacy application
- Easy to deal with fireall (port 80 is not blocked)
- Disadvantages
- Ambiguous standards - different companies
- Performance overhead due to serialization and deserialization
- When to use?
- SOAP
- format
- WSDL
- Contract
- Topics
- Top down
- Bottom up
- JAX-WS
- Apache CXF - stack
- Features
- Contract first: Top down - WSDL first
- First WSDL file is defined - it has all the info about ws
- Generate Java stubs using tools like wsdl2java
- Implement web services endpoint (using stub)
- Advantages:
- Sign off contract with consumer upfront
- Everyone will be on the same page
- Improves inter operability
- Code first approach disadvantage: If web service uses a new data structure but legacy consumer does not understand, ws is not useful
- Consumers can ensure the availability
- We can give to consumer right at the beginning
- Parallel development
- Faster integration
- Code first: Botton up
- Write Java code and annotate with JAX-WS spec
- Generate WSDL using java2wsdl (JAX-WS)
- Advantages:
- We can integrate legacy applications (to expose as web service)
- When to use which one?
- Contract first as much as possible for scratch development
- Code first when we want to expose out legacy applications as web services
- For others to consume (sharing)
- WSDL is easy to understand (technical and non-technical people)
- WSDL first: Faster integration
-
Comprises of Specification and API
- Specification: Consists of rules and guidelines
- Glassfish: Reference implementation of the specification
- CXF: Implementation
- Glassfish: Reference implementation of the specification
- API: Consists of Annotations
- Developers can mark classes with annotations (for providers and consumers)
- Specification: Consists of rules and guidelines
-
Core annotations:
@javax.jws.WebService public class OrderService // end point @javax.jws.WebMethod @WebResult(name = "order") Order getOrder(@WebParam(name = "orderId") Long orderId) @javax.xml.ws.WebFault- For custom exceptions which are converted to SOAP fault (extends
Exception)
- For custom exceptions which are converted to SOAP fault (extends
-
Binding
@javas.jws.soap.SOAPBinding-
To specify type of binding
-
How SOAP message gets generated
-
Default:
document\literal@SOAPBinding(sytle = Style.RPC, use = Use.LITERAL)
-
-
Incoming requests and outgoing responses can be mapped to java objects in a custome manner
@javax.xml.ws.RequestWrapper @javax.xml.ws.ResponseWrapper- JAX-WS standard does it well so not required usually
-
- Java Architecture for XML Binding
- Easy way to map Java class and XML schema hiding the complexity
- No need to deal with STAX parser or DOM parser
- JAXB is for XML as Hibernate is for SQL
- Easy way to map Java class and XML schema hiding the complexity
- Tools provided by JAXB - Three
- XJC - XML Schema Compiler
- Generates Java classes from a given XML Schema
- Internally used for WSDL first development
- SchemaGen - Generates XML Schema from Java classes
- Runtime API:
- Marshal Java objects into XML
- Un-Marshal XML into Java objects
- XJC - XML Schema Compiler
- Runtime API
- Marshalling class
- Unmarshalling class
- Annotations
- Reference Implementation
- CXF uses reference implementation
- Current version of JaxB (as of then) 2.2
- JAXB is part of JDK
schemagenandxjccommands exist- Real time, plugins are used
- Maven jaxb plugin
-
org.jvnet.jaxb2.maven2<dependency> <groupId>org.jvnet.jaxb2.maven2</groupId> <artifactId>maven-jaxb2-plugin</artifactId> <version>0.14.0</version> </dependency>
-
- Maven jaxb plugin
- New maven project
- New schemas
- Use JAXB Plugin
- Generate the stubs and use them to serialize and deserialize
main/xsd- Download schemas from resources https://www.udemy.com/java-web-services/learn/v4/t/lecture/2453636?start=0
- paste them under
xsdfolder
- paste them under
- Open
pom.xmlfrom the download folder- Copy
buildsection and paste
- Copy
- New source folder
src/generated - Run as > Maven generate sources
- Open
global.xjb- configuration<bindingDirectory>- where bincing file is present- Tells how java code should look like when generated
- Root element:
jaxb:bindings <xjc:simple>- it includes@XmlType(...)- default even if removed<xjc:serializable uid="-1">-serialVersionUID<jaxb:javaType name="java.util.Calendar" xmlType="xs:dateTime" ...- Usesjava.util.Calendarwhen generating date fields@XmlType- used to define order of elements@XmlElement- name can be defined@XmlAttribute- specifies xml attribute
- Root element:
package-info- used for java docsObjectFactory.java- If data structures in xmls do not map to a Java class- For generating object of the data structure
-
Marshalling: Converting Java objects to xml
-
Un-Marshalling: Converting xml to Java
-
New class:
com.bharath.trainings.jaxb.JAXBDemoJAXBContext context = JAXContext.newInstance(Patient.class); Marshaller marshaller = context.createMarshaller(); Patient patient = new Patient(); patient.setId(123); patient.setName("Bharath"); StringWriter writer = new StringWriter() marshaller.marshal(patient, writer); System.out.println(writer.toString()); Unmarshaller unMarshaller = context.createUnmarshaller(); Patient patientResult = (Patient) unMarsheller.unmarshal(new StringReader(writer.toString()); System.out.println(patientResult.getName());
- Java API for XML based web services
- Spec: For stack implementation
- API: Annotations
- Tools used to develop web services
- Java Stacks:
- Apache CXF (popular)
- Apache AXIS
- METRO
- WebLogic
- Web Sphere
- .Net Stacks:
- WCF
- Java Stacks:
- Popular Webservices stack in Java
- Web services stack/engine provides with various tools to build and run web services
- Developers can focus on business logic
- CXF:
- Implements both JAX-WS and JAX-RS standards
- Can be used build producers and consumers
- Comes with SOAP/REST Engine
- Serializes and De-Serializes messages back and forth to Java objects
- Publishes and dispatches request to service endpoint
- XML <- SOAP/REST Engine -> Java Object <-> WS Endpoint Method
- Implements almost all web service standards (just configuration is required using configuration files)
- WS-Security
- WS-Policy
- WS-Transactions
- ...
- Tools
wsdl2java- generates code from WSDL code- Used to generate WS client using stubs generated
java2wsdl- code first development
- Plugins for ant and maven
- Include tools as ant tasks or maven plugin
- Uses Spring Configuration to configure web services endpoints and other features
- Annotations or config file
- Interceptors or Handlers can be used to extend CXF (custom code)
- Documentation and Samples
- http://cxf.apache.org/
- Web services stack/engine provides with various tools to build and run web services
- Add cxf spring boot dependency
- When project gets created
cxf-spring-boot-starter-jaxrs- other jar files for RESTFul services and SOAP services are installed
- Publishing RESTFul endpoints very easy
-
application.propertiescxf.jaxrs.component-scan=true-
Endpoints are automatically discovered and published
-
Web application context
server.context-path=/restws
-
-
- When project gets created
- Easy way to build Java apps
- Spring Framework in Easy Steps: Section 25
- Open STS
- Name: hellowebservice
- Group: com.bharath.ws.soap
- Description: Hello SOAP Service
- Package: same as Groupname
pom.xml- Search for
cxf spring boot jax ws maven dependency - Pick latest version
- Copy to
<dependencies>section
- Search for
- Right click on Package > New > Class
-
HelloWS@WebService public class HelloWS { @WebMethod public String hello() { return "hello"; } }
-
-
New Java Class >
com.bharath.ws.soap.config.WebServiceConfigimport javax.xml.ws.Endpoint; import org.apache.cxf.Bus; import org.apache.cxf.jaxws.EndpointImpl; import org.springframework.context.annotation.Configuration; @Configuration public class WebServiceConfig { @Autowired private Bus bus; @Bean public Endpoint endpoint() { Endpoint endpoint = new EndpointImpl(bus, new HelloWS()); // bus - CXF runtime endpoint.publish("/hello"); return endpoint; } }
- Right click on project > Run as > Spring Boot Application
- Open http://localhost:8080/services (cxf feature - services are exposed here)
- Click on link to open WSDL
-
Webservices name configuration
-
application.propertiesserver.servlet.context-path=/hellows cxf.path=/ # don't use /services
-
- Open SoapUI
- File > New Soap Project
- Initial WSDL: Paste WSDL URL
- Project Name: hellows
- Open and double click the request
- Hit play button
-
CXF has logging feature to log in coming SOAP requests and outgoing SOAP responses to log file or console
-
One
HelloWSclass@Features(featurs = "org.apache.cxf.feature.LoggingFeature") public class HelloWS { ... -
Run as Spring boot application
-
Re-run test in SOAP UI
- Spring Boot version: 2.x
- CXF: 3.2.4
- Search for
spring boot 2 starter mavenin Google- Copy the version and paste in spring starter version
- Change to 3.2.4
- Open
.m2and removerepositoriesfolder - Run
mvn clean - Run
mvn install - Run Maven > Update Project
- Open
application.properties- Use
server.servlet.context-pathinstead forserver.context-path
- Use
- CXF implements JAX-WS and JAX-RS
- Code first web services
- SOAP Engine to serialize and desarialize requests
- Dispatches requests to appropriate methods
- WS-* standards are implemented
- Security
- Attachments
- ...
- It has huge user base, docs and samples
- Advantages of RESTFul Web Services and when to use them
-
REST?
- Representational State Transfer
- WEB Browser -HTTP GET-> WEB SITE -VIDEO-> WEB BROWSER
-
Princiles:
- Creation, Read, Update, Delete: Single interface to do them
- HTTP provides method POST, GET, PUT, DELETE
- URI is provided for each resource
-
POST /patients
<patient> <name>john</name> <patient> -
200 OK
<id>1</id> -
GET /patients/123
-
200 OK
<patient> <id>123</id> <name>john</name> </patient> -
PUT /patients
<patient> <id>123</id> <name>john smith</name> </patient> -
200 OK
-
DELETE /patients/123
-
200 OK
-
- Creation, Read, Update, Delete: Single interface to do them
-
Since HTTP supports multiple data formats, REST can consume and provide data in multiple formats (XML, JSON, ...)
- XML: .Net App to Java
- JSON: Javascript
- Text: images ...
-
REST: Stateless
- Exchange of respresentational state between provider and consumer
- Session is not stored in Server
- Exchange of respresentational state between provider and consumer
-
Key principles
- Single HTTP interface
- Easy to access: URIs
- Multiple representations
- Scalability - can be deployed on several servers
- Softwares offer CRUD operations: REST provides methods that are generic
http://www.hospital.com/patients/patients/{id}/prescriptions/prescriptions/{id}
- Interoperability:
- Any app written in any language or running on any platform can communicate with any other app in many data formats
- REST client (HTML/JavaScript) -JSON-> REST Provider (Java)
- REST client (.NET) -XML-> REST Provider (Java)
- REST client (Python) -CSV-> REST Provider (Java)
- Any app written in any language or running on any platform can communicate with any other app in many data formats
- Statelessness
- State of user maintained on client
- Browser can maintain state (Using JavaScript)
- State of user maintained on client
- Scalability: Because of statelessness provides idempotency
- Multiple servers can serve at the same time using load balancer and caching
- When consumer and producer have a mutual understanding (well defined contract)
- Unline SOAP - which has WSDL
- REST does not have a way to express contract (handled with documentation and examples)
- Unline SOAP - which has WSDL
- Multiple data formats: if many formats are to be supported (SOAP supports only XML)
- Bandwidth and Memory is limited: (Handheld devices) No SOAP overhead, JSON instead of XML
- Stateless apps: If app survives server restart
- Caching is possible: responses can be cached (performance boost)
- Existing logic can be exposed easily using REST - new interfaces can consume them (Developer productivity) - reusability of business logic
- Standard interface
- Single interface
- easy to access (URI)
- Multiple data formats at the same time
- Stateless (session managed by client) - survives server restart
- No formal contract
- No overhead (lighweight)
- Download STS for the platform and install
- Preferences > JRE > Installed JREs > Select JDK folder
- Patient management system
- Chrome REST Plugin
- RESTFul client
- Java
- JavaScript
- Patient management system
- ADD, READ, DELETE, UPDATE patient information
- Steps:
- Identify the resources (exposed as rest resources)
- Build URIs to access resources
- Assign HTTP methods for CRUD operations
- Choose data format
- System
- DTOs:
- Patient can have multiple Prescriptions
- Each Prescription can have multiple Medicnes
- Service:
- PatientService:
- getPatient
- updatePatient
- addPatient
- deletePatient
- getPrescription
- PatientService:
- DTOs:
- Steps Implementation:
-
Nouns in the System become the RESTFul resources
- Patients
- Prescriptions
- Medicines
-
URIs:
- Creation of Patient:
/patients
- Read a Patient
/patients/{id}
- Update a Patient
2.
/patients(data should have id) - Remove a Patient
3.
/patients/{id}1./patients- for removing all patients
- Creation of Patient:
-
Methods
- GET: Read operations (idempotent)
- POST: Creations operations (non-idempotent - multiple changes state of the system)
- PUT: Update operations (idempotent)
- DELETE: Delete operations
-
Data formats:
- XML: popular
- JSON
- Actual data:
-
Read: GET /patient/123
<Patient> <id>123</id> <name>Bharath</name> </Patient> -
Creation: POST /patient
<Patient> <name>Bharath</name> </Patient> <Patient> <id>123</id> <name>Bharath</name> </Patient> -
Update: PUT /patient
<Patient> <id>123</id> <name>Bharath</name> </Patient> HTTP1.1 200 OK -
Delete: DELETE /patient/123
HTTP/1.1 200 OK
-
-
Real app: Schema is given to client to understand what data is being transferred
-
- JAX-RS: Java API for XML based REST Services: API
- It has Spec and API
- Spec: For web service engines and stacks (Set of rules and guidelines)
- Apache CXF
- Jersey
- API: For developers
-
Annotations:
import javax.ws.rs.*@Path("/users/{username}") // maps relative uris to class or method- username: pathparam - bound to java parameters
-
HTTP Methods:
@GET // method is marked for GET requests -
Data formats:
@Consumes("text/plain") @Produces({"application/json", "application/xml"})- HTTP MIME types: application/json, applicaction/xml
-
Parameter values:
@PathParam @QueryParam @FormParam (during form submission to a Java object) -
Exception Mappers:
@Provider // for custom exception mappers (map Java Exceptions to HTTP error codes)
-
- Spec: For web service engines and stacks (Set of rules and guidelines)
- It has Spec and API
-
Apache CXF: Add cxf spring boot dependency
cxf-spring-boot-starter-jaxrs- jars required are transitively added
-
application.properties (automatic discovery of endpoints - no config file)
cxf.jaxrs.component-scan=true server.context-path=/restws
- Steps:
- Spring Boot Project:
- File > New Spring Starter Project
- Name: restws
- group: com.bharath.restws
- Artifact: restws
- Version: 0.0.1-SNAPSHOT
- Description: Patient REST Services
- Package: com.bharath.restws
- Dependencies: cxf - Apache CXS (JAX-RS)
- File > New Spring Starter Project
- Spring Boot Project:
- Patient model class:
- Endpoint
- Mark with JAXB and JAX-RS annotations
- Steps:
-
com.bharath.restws.model.Patient
@XmlRootElement(name = "Patient") public class Patient { private long id; private String name; // getters and setters } -
com.bharath.restws.PatientService (Interface)
@Path("/patientservice") public interface PatientService { } -
com.bharath.restws.PatientServiceImpl
@Service // to discover at runtime public Class PatientServiceImpl implements PatientService { }
-
-
PatientServiceImpl
@Service //@Component - if @Service does not work public class PatientServiceImpl implements PatientService { Map<Long, Patient> patients = new HashMap<>(); // since singleton is returned each time, this is persistent Long currentId = 123; public PatientServiceImpl() { init(); } void init() { Patient patient = new Patient(); patient.setId(currentId); patient.setName("John"); patients.put(patient.getId(), patient); } }
-
Methods:
- GET, POST, PUT: http://localhost:8080/patientweb/services/patientservice/patients
- GET One Patient or DELETE one Patient: http://localhost:8080/patientweb/services/patientservice/patients/123
-
Code:
public interface PatientService { @Path("/patients") @GET List<Patient> getPatients(); }-
Implement the method
@Override public List<Patient> getPatients() { Collection<Patient> results = patients.values(); List<Patient> response = new ArrayList<>(results); return response; }
-
-
Configure: application.properties
# cxf.path=/services - http://localhost:8080/restws/services/patientservice/patients cxf.jaxrs.component-scan=true server.context-path=/restwshttp://localhost:8080/restws/patientservice/patients
- Run as SpringBootApp (launches embedded tomcat)
- Launch PostMan
- Select GET
localhost:8080/restws/patientservice/patients(cxf exposes)
-
New method
@Path("/patients/{id}") @GET Patient getPatient(@PathParam(value = "id") Long id); -
Implement method
@Override public Patient getPatient(Long id) { return patients.get(id); } -
Relaunch app
-
Test in Postman:
- GET localhost:8080/restws/services/patientservice/patients/123
-
New method
@Path("/patients") @POST Response createPatient(Patient patient); -
Implement method
@Override public Response createPatient(Patient patient) { patient.setId(++currentId); patients.put(patient.getId(), patient); return Response.ok(patient).build(); }
-
localhost:8080/restws/services/patientservice/patients -
Select raw
<Patient> <name>Bharath</name> </Patient>- Change Text to XML (application/xml)
-
One more
-
Test other methods
-
New method
@Path("/patients") @PUT Response updatePatient(Patient patient); -
Implement method
@Override public Response updatePatient(Patient patient) { Patient currentPatient = patients.get(patient.getId()); Response response; if (currentPatient != null) { patients.put(patient.getId(), patient); response = Response.ok().build(); } else { response = Response.notModified().build(); } return response; }
- Test Update:
-
Restart app
-
PUT
localhost:8080/.../patients -
Body > Raw
-
Text XML(text/xml)
<Patient> <id>125</id> <name>Bob</name> </Patient>- 304 - not modified
-
Add and test again
-
-
New method
@Path("/patients/{id}") @DELETE Response deletPatient(@PathParam("id") Long id); -
Implement method
@Override public Response deletePatient(Long id) { Patient patient = patients.get(id); Response response; if (patient != null) { patients.remove(patient.getId()); response = Response.ok().build(); } else { response = Response.notModified().build(); } return response; } -
Test: Restart app
- DELETE localhost:8080/.../patients/123;
- Test and run GET
- Try to delete again: 304 - not modified
- Steps:
- Add Jackson Dependencies (serializes and de-serializes)
- jackson-jaxrs
- jackson-xc (xml compatability dependency)
- Change the configuration
- @Consumes and @Produces
- Add Jackson Dependencies (serializes and de-serializes)
- jackson-jaxrs maven
- latest version
- Paste both in dependencies section
- application.properties (tells apache-cxf about jackson to be used as the provider)
-
Remove cxf.jaxrs.component-scan=true
-
Add
cxf.jaxrs.classes-scan=true cxf.jaxrs.classes-scan-packages=org.codehaus.jackson.jaxrs, com.bharath.restws #base package is enough
-
-
PatientService.java
@Consumes("application/xml,application/json") @Produces("application/xml,application/json") // interface, class, method ... public interface PatientService {
- Restart app
- Goto Postman
- Tell explicitly that client needs xml
- Headers
Accept:application/json
- Creation: JSON (application/json)
- Headers
- Tell explicitly that client needs xml
- Identify resources (nouns)
- URIs for resources
- Assign HTTP Methods
- Choose data formats
- JAX-RS - Specification, API
- Annotations
- URI Mapping
- HTTP Methods
- Data Format
- Exception Mapping
- Parameters
- Success codes: 200 to 399
- 200 OK
- Failure codes: 400 to 599
- Types:
- Standard Errors: Across REST apps (wrong URI, wrong datatype ...)
- Application Errors: Specific to app
- Types:
-
Returning standard error codes to client
- WebApplicationException(Response.Status.NOT_FOUND) - throw an instance of this class
- Response.Status - has standard error codes
- Specific exceptions (instead of an instance of above class)
BadRequestException- 400NotAuthorizedException- 401ForbiddenException- 403InternalServerException- 500ServiceUnavailableException- 503 - if server is down temporarily
- WebApplicationException(Response.Status.NOT_FOUND) - throw an instance of this class
-
Example:
public Patient getPatient(Long id) { if (patients.get(id) == null) throw new WebApplicationException(Response.Status.NOT_FOUND); ... }-
Or
throw new NotFoundException();
-
-
We deal with multiple layers
- Integration layer (REST WS)
- Service Layer (business logic)
- Data Access Layer
-
If an exception occurs in Integration layer, Service layer or Data access layer, we must handle that in integration layer and send a useful message to client
- Exception Mappers can be used
-
Example:
public Response updatePatient(Patient patient) { ... } else { throw new PatientBusinessException(); } } public PatientBusinessException extends RuntimeException { ... }- Does not send user friendly exception
-
com.bharath.restws.PatientBusinessExceptionMapper
@Provider // tells cxf that this is runtime component public class PatientBusinessExceptionMapper implements ExceptionMapper<PatientBusinessException> { @Override public Response toResponse(PatientBusinessException e) { return Response.status(404).build(); } }
-
JSON Response
toResponse(...) StringBuilder sb = new StringBuilder(); sb.append("{"); sb.append("\"status\":\"error\""); sb.append(","); sb.append("\"message\":\"Try again later\""); sb.append("}"); return Response.serverError().entity(sb.toString()).type(MediaType.APPLICATION_JSON).build();
- Two types:
- Standard errors: General
- Application errors: specific to business
- Apache HTTPClient lib
- JAX-RS Client API (Oracle) - CXF (Vendor)
ClientBuilder(M): Allows creation of an instance ofClientClient(M): Communication channel between RESTFul client and RESTFul resources- Used for creation of
WebTarget
- Used for creation of
WebTarget(M): Points to unique RESTFul resourceInvoker.Builder(M): Used for invocation of methodsEntity(M): Represents data (with datatype)- Serialization is taken care of
- Standalone Spring Boot project
- New > Spring Starter Project
- Name: restwsclient
- Description: Patient REST Client
- New > Spring Starter Project
- pom.xml
- search for cxf rest client
- cxf-rt-rs-client latest
- Paste after spring-boot-starter
- search for cxf rest client
- RESTFul Client
-
DTO - com.bharath.restwsclient.model.Patient.java
@XMLRootElement(name = "Patient") ... -
com.bharath.restwsclient.PatientWSClient
Client client = ClientBuilder.newClient(); WebTarget target = client.target("http://localhost:8080/restws/patientservice/patients/123"); Builder request = target.request(); Response response = request.get(); System.out.println(response.getStatus()); Patient patient = request.get(Patient.class); System.out.println(patient.getId()); System.out.println(patient.getName());
-
-
Dynamically pass parameters
priavet static final String PATIENT_SERVICE_URL = "http://.../patientservice"; public static void main(String[] args) { ... WebTarget target = client.target(PATIENT_SERVICE_URL).path("/patients").path("/{id}"); target.resolveTemplate("id", 123); ... }
-
Code
patient.setName("Bharath"); WebTarget putTarget = client.target(PATIENT_SERVICE_URL).path("/patients"); Response updateResponse = putTarget.request().put(Entity.entity(patient, MediaType.APPLICATION_XML)) System.out.println(updateResponse.getStatus());
-
Code
Patient newPatient = new Patient(); newPatient.setName("Bob"); WebTarget postTarget = client.target(PATIENT_SERVICE_URL).path(PATIENTS); Patient createdPatient = postTarget.request().post(Entity.entity(patient, MediaType.APPLICATION_XML), Patient.class); // second arg: Response type System.out.println("Created Patient ID: " + createdPatient.getId());
-
Client and Response needs to be closed
updateResponse.close(); // socket resources will not be held up client.close();- Don't wait for garbage collection
- Delete a patient
- ClientBuilder
- Client
- WebTarget
- Entity: wraps request and response objects
- Invoker.Builder
@PathParam("id") int id->/Patient/123- Others
@QueryParam@FormParam@HeaderParam@CookieParam- ...
- Airline Reservation System:
- PassengerService
- getPassengers
- addPassengers
- PassengerService
- New Project > Spring Starter Project > PassengerService
- Apache CXF JaxRS - dependency
-
com.bharath.restws.model.Passenger.java
public class Passenger { private int id; private String name; // Getters and setters } -
com.bharath.restws.PassengerService
public interface PassengerService { List<Passenger> getPassengers(); Passenger addPassenger(Passenger passenger); } -
com.bharath.restws.PassengerServiceImpl
-
Implementation
@Service // Spring public class PassengerServiceImpl implements PassengerService { List<Passenger> passengers = new ArrayList<>(); int currentId = 123; @Override public List<Passenger> getPassengers() { return passengers; } @Override public Passenger addPassenger(Passenger passenger) { passenger.setId(currentId++); passengers.add(passenger); return passenger; } } -
Passenger.java
@XMLRootElement public class Passenger { } -
PassengerService
@Path("/passengerservice") @Produces("application/xml") @Consumes("application/xml") public interface PassengerService { @Path("/passengers") @GET List<Passenger> getPassengers(); @Path("/passengers") @POST Passenger addPassenger(Passenger passenger); }
-
Example:
GET localhost:8080/restinjection/services/passengerservice/passengers-
application.properties
cxf.jaxrs.component-scan=true server.context.path=/restinjection
-
-
Example: Add passenger
POST localhost:8080/restinjection/services/passengerservice/passengers - application/xml <passenger> <name>Bob</name> </passenger> GET localhost:8080/restinjection/services/passengerservice/passengers
-
Paging:
@Override public List<Passenger> getPassengers(int start, int size) { // ... } -
Interface
List<Passenger> getPassengers(@QueryParam("start") int start, QueryParam("size") int size); -
Example:
localhost:8080/restinjection/services/passengerservice/passengers?start=1&size=25
-
Example:
Override public void addPassenger(String firstName, String lastName) { // ... System.out.println(firstName); System.out.println(lastName); }-
Interface
@Consumes("application/xml, application/x-www-form-urlencoded") ... void addPassenger(@formParam("firstName") String firstName, @formParam("lastName") String lastName)
-
-
Testing
localhost:8080/restinjection/services/passengerservice/passengers?start=1&size=25 x-www-form-urlencoded firstName: Bharath lastName: Thippireddy
-
Example: agent
void addPassenger(..., @HeaderParam("agent") String agent); public void addPassenger(..., String agent) { // ... System.out.println(agent); } -
Testing:
Headers: agent: United Airlines
-
We can read all the fields coming at once using
HttpHeadersvoid addPassenger(..., @Context HttpHeaders headers); void addPassenger(..., @Context HttpHeaders headers) { // ... MultivalueMap<String, String> allHeaders = headers.getRequestHeaders(); Set<String> headerKeys = allHeaders.keySet(); for (String key: headerKeys) { System.out.println(key); System.out.println(headers.getHeaderString(key)); } }
-
HttpHeaders object has the cookies
Map<String, Cookie> cookies = headers.getCookies(); Set<String> cookieKeys = cookies.keySet(); for (String eachCookieKey: cookieKeys) { System.out.println("---------- Cookies ----------"); System.out.println(eachCookiesKey); System.out.println(cookies.get(eachCookiesKey).getValue()); } -
PostMan:
- Cookies
- Add Cookie
- New key-value pair
@PathParam- to retrieve value of URI@QueryParam@HeaderParam@CookieParam- cookie injection@FormParam
- Synchronous:
- Client sends request
- Client waits for response
- Server sends 200 response
- Client processes the response
- Asynchronous:
- Example: ATM, Bank Teller, Account Holder Mobile, Check Processor
- Bank Teller sends checks to Check Processor (for processing) - asynchronous (by spawning multiple threads)
- Immediately Check processor sends 202 (acceptance of request)
- Check processor sends 200 response to client
- Bank Teller sends checks to Check Processor (for processing) - asynchronous (by spawning multiple threads)
- Asynchronous RESTful Provider/Server
- Asynchronous RESTful Client API
- Method:
- Polling - checks frequently if request has been processed
- Callback - methods will be called when response comes (JAX-RS 2.0) back
- Method:
- Example: ATM, Bank Teller, Account Holder Mobile, Check Processor
- Implementation of Provider:
@javax.ws.rs.container.Suspendedjavax.ws.rs.container.AsyncResponse
- Implementation of Client
javax.ws.rs.client.AsyncInvokerjava.util.concurrent.Future- to process response asynchronouslyjavax.ws.rs.client.InvocationCallback- to implement callback on client side
-
New spring starter project: restwsasync
- Description: Patient REST Async Services
Apache CXF JaxRS
-
application.properties
cxf.jaxrs.component-scan = true server.context-path=/restwsasync
-
Model class:
Check(com.bharath.restws.model)public class Check { private String checkNumber; private String accountNumber; private Double amount; // getters and setters } -
Interface: CheckProcessor
@Path("/checkprocessingservice") public interface CheckProcessor { @POST @Path("/checks") public Boolean processChecks(ChecksList checksList); } package com.bharath.restws.model; public class ChecksList { // Wrapper Class private List<Check> checks; // getter and setter } pubic class CheckProcessorImpl implements CheckProcessor { @Override public class CheckProcessorImpl implements CheckProcessor { return null; } } @XMLRootElement public class ChecksList { // ... }
-
CheckProcessorImpl.java
@Override public void processChecks(AsyncResponse response, ChecksList checksList) { // logic response.resume(true); // returns asynchronously } public void processChecks(@Suspended AsyncResponse response, ...); // the method should be asynchronous - CXF finds it out
-
Multiple threads
@Override public void processChecks(AsyncResponse response, ChecksList checksList) { // logic new Thread() { public void run() { // processing response.resume(true); } }.start(); }
- New Spring startup project
-
pom.xml
<dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-rs-client</artifactId> <version>3.2.1</version> </dependency>
-
-
com.bharath.restws.client.CheckProcessingClient
public static void main(String[] args) { Client client = ClientBuilder.newClient(); WebTarget target = client.target("http://localhost:8080/restwsasync/services/checkprocessingservice/checks"); AsyncInvoker invoker = target.request().async(); Future<Boolean> post = invoker.post(Enity.entity(new ChecksList(), MediaType.APPLICATION_XML), Boolean.class); // polls service for response to come back try { System.out.println(response.get()); // polls and waits } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } }
-
CheckProcessorImpl.java
@Service public class CheckProsessorImpl implements CheckProcessor { // ... }
-
CheckProcessorImpl.java
if (checksList == null || checksList.getChecks() == null || checksList.getChecks().size() == 0) { response.resume(new BadRequestException()); // asynchronously throws exception }
-
CheckProcessingClient.java
} catch (ExecutionException e) { if (e.getCause() instanceof BadRequestException) { BadRequestException bre = (BadRequestException) e.getCause(); System.out.println("Please send a valid list of checks"); } }
- Client sends a request
- Provider sends 202 header
- Provider sends 200 response or 4xx response
- JAX-RS 2.0 provides Provider and Client
- Client: Polling or Callback
AsyncInvoker- used to do pollingInvocationCallback- write our own callbackFuture- used to handle async response
- Provider:
@Suspended- used to mark object of typeAsyncResponse(used to send asynchronous response back to client)
- Client: Polling or Callback
- It is part of HTTP standard (used by client and server to exchange authentication information in headers in a standard manner)
- Works across platforms and languages
- Configuration: Refer to configuring-Basic-Security.rtf
- Configuring security constraint
- open
web.xmlunderWEB-INF - Paste
<security-constraint>and<login-config>- Security constraint: Used to specify constraints we want
/*- any uri pattern should be secure/*.html- secures only html pages
<http-method>- to which method the security is applicable (GET,PUT,POST,DELETE)<auth-constraint>- defines the role which use must have to access the endpoint(s)- Role: Defined in Tomcat's
tomcat-users.xml(confdirectory)<role rolename="tomcat"/><user username="tomcat" password="tomcat" roles="tomcat"/>
- Role: Defined in Tomcat's
<login-config>- what method of authentication are we using -BASIC
- Security constraint: Used to specify constraints we want
- open
- Run the app:
- As soon as web app launches, browser prompts for basic authentication (browser also implements basic authentication)
- If browser is closed and cache cleared, browser prompts again for basic authentication
- Configuring security constraint
-
RESTful e-commerce website - handles products for customers
-
getProducts- user -
addProduct- admin/products @GET @POST
-
-
Spring security
- Authentication
- Authorization
-
Download the sample project and open in eclipse
spring-security-config- dependency in pomspring-security-web- dependency in pom
-
Open src/main/webapp/WEB-INF/web.xml
<context-param> <param-name>ContextConfigLocation</param-name> <param-value> WEB-INF/beans.xml WEB-INF/security.xml </param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> -
Important files: src/main/webapp/WEB-INF/beans.xml and src/main/webapp/WEB-INF/security.xml
-
Open
ProductServiceImplclasspublic List<Product> getProducts() { return products; } public int addProduct(Product product) { product.setId(++productId); products.add(product); return productId; } -
Open
ProductServiceinterface@GET @Path("/products") List<Product> getProducts(); @POST @Path("/products") int addProduct(Product product);
-
Open beans.xml
<jaxrs:server id="productws" address="/productService"> <jaxrs:serviceBeans> <ref bean="productService" /> <!-- for CXF --> </jaxrs:serviceBeans> </jaxrs:server> <bean id="productService" class="com.bharaththippireddy.tranings.jaxrs.ProductServiceImpl" />
- Run As > Maven Clean
- Run As > Maven Install
- Run As > Run on Server (Tomcat)
- Install Advanced REST client in Chrome
- Drop down
- Extensions
- Advanced REST client
- Options
- Request
- Goto HOWTO.txt in project
- Paste URL in Chrome
- Send GET request
- Send POST request
- Paste URL in Chrome
- Spring provides following services
- Authentication
- Authorization
- Spring provides security at the following levels
- URL level
- Method level
- Object level
- Steps:
-
Add dependencies in
pom.xmlspring-security-corespring-security-configspring-security-web
-
Add Filter: Spring uses Filter Servlet (
DelegatingFilterProxy)- In
web.xml
- In
-
SpringConfiguration.xml<global-method-security /> <!-- for enabling security annotations --> <http /> <!-- what type of security --> <AuthenticationManger /> <!-- For users and roles --> -
@Security("ROLE_NAME")ROLE_NAME: That can access RESTful methods
-
-
Open Eclipse
-
Open
pom.xmlspring-security-core spring-security-config spring-security-web spring-security-taglib (for MVC) -
web.xml
<filter> <filter-name>springSecurityFilterChain</filter-name> <!-- This name is used by spring to kick in the default security framework - always used this name --> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> <!-- Secure entire web app --> </filter-mapping>
-
security.xml
<security:global-method-security secured-annotations="enable" /> <!-- Enables spring security annotations on method level --> <security:http> <security:http-basic /> <!-- Enables basic security --> </security:http> <security:authentication-manager> <security:authentication-provider> <security:user-service> <!-- One of the services, others LDAP, JDBC ... --> <security:user name="customer" password="customer" authorities="ROLE_CUSTOMER" /> <security:user name="admin" password="admin" authorities="ROLE_CUSTOMER,ROLE_ADMIN" /> </security:user-service> </security:authentication-provider> </security:authentication-manager>
-
ProductService@Secured("ROLE_CUSTOMER") @GET @Path("...") ... @Secured("ROLE_ADMIN") @POST @Path("...") ...
-
Right click on project
mvn cleanmvn install
-
Right click and Run on Server
-
Open
http://localhost:8080/springsecurity/servicesin browser- wadl url exists
-
Open Advanced REST Client in chrome
- Open HOWTO.txt and paste URL
- Login using customer/customer credentials
-
Select POST and paste
<Product> <description>Hibernate</description> </Product>- Change to
application/xml 403forbidden exception- Console throws
Access is deniedexception
- Console throws
- Change to
-
Another way to authenticate
-
Open Form in Chrome
Authorization (click on construct link)- Enter credentials (basic authentication header is generated)
-
-
Right click on package: New > Class
-
Name:
SecurityExceptionMapper -
Implements:
ExceptionMapperimport org.springframework.security.access.AccessDeniedException; public class ... ExceptionMapper<AccessDeniedException> { @Override public Response toResponse(AccessDeiniedException arg0) { return Response.status(Response.Status.FORBIDDEN).build(); } }
-
-
beans.xml
<jaxrs:server ...> <jaxrs:providers> <bean class="com.bharaththippireddy.trainings.jaxrs.SecurityExceptionMapper" /> </jaxrs:providers> </jaxrs:server> -
Test adding product using customer credentials
- Customer error message can be sent in body
- Publish Endpoints
- Configure Spring Security
- Configure dependencies
- Configure delegating proxy filter (loaded when we start server because they are context parameters - loaded even before the servlets)
- Enable security annotations
- Configure Basic authentication and authorization
- Define roles, usernames and passwords
- Map methods to the roles
- Test in Chrome REST plugin
- Configured method level security
- Authentication and Authorization
- Application verifies identity
- Application allows access only to authorized services (permissions)
- OAuth: Authentication and authorization standard
- Allows User to access service without knowing user id and password
- Scenario:
- User is using app A
- A wants data from B (User does not want to share credentials of B with A)
- A redirects User to B
- User logs into B
- B shares a security token with A
- A gets data from B using the token
- Example:
- Federated authentication: One app uses another app for login
- Delegated authorization: Authorization process is delegated to another app
- Tax Site redirects to Google Login for Google Drive
- User logs into Google
- Tas Site gets token from Google
- Using the token, Tax site saves the tax documents in Google drive
- OAuth allows an app to perform actions on user's behalf (with the permission of the user) with the authorization given by the user
- oauth.net/2/
- Why?
- Example: Job portals redirects to LinkedIn
- Reasons:
- Trust
- Stealing (if username and password given to Job portals - abuse)
- Unlimited access (if username and password given to Job portals - get authorized to all the services and resources)
- Revocation (not possible if username and password are given)
- When?
- If user wants app1 to use services of app2 but does not want to give credentials to app2
- When not?
- Not for simple apps
- Use HTTP basic over SSL
- Form based authentication over SSL
- Not for simple apps
-
Example:
- End User is accessing JavaWorld.com
- If End User wants to comment on an article
- JavaWorld.com asks us to login to Google
- JavaWorld.com uses oauth to communicate with google and gets authentication information
-
Steps:
- JavaWorld.com registers with Google and gets a client ID
- JavaWorld.com redirects to http://googleapis.com/oauth?client_id=javaworld&state=1234567890&redirect_uri=http%3A%2F%2Fjavaworld.com
- state: current session state of user (when user gets back to JavaWorld.com after authentication, he is put into this state)
- redirect_uri: link to which google should redirect to once authentication is successful
- User logs in
- Google authenticates and redirects to http://javaworld.com/state=1234567890&code=0002222
- code: unique generated by google
- JavaWorld takes code and sends to Google
- Google gives back a unique token to JavaWorld (2b325245341bc23423423523423412abc)
- JavaWorld uses the token to communicate with Google to get any kind of information (authorized only) from Google (using Google API)
-
Roles in OAuth:
- Resource server: server that hosts user resources and protected by OAuth
- Resource Owner: End user say
- Client: App that wants to access resources of an End User on the Resource Server
- Authorization Server: Server that generates unique code and token
-
Google, Facebook, Twitter: Do not use OAuth as it is
- OAuth has guidelines but not protocol (does not define how user must authenticate or what parameters need to be sent)
-
OAuth with Java:
- Libraries available to convert apps to Client or Resource Server
- Goto about OAuth in oauth.net/2/: Look for Java implementation
- Search for Apache CXF oauth: JAX-RS Auth - how to implement oauth for the app
- Google oauth playground:
- Search for it
- Sample app that allows us to access RESTFul services and support OAuth
- Use Contacts REST service
- Check and Authorize
- Gives authorization code
- Click on Exchange authrorization code for token
- Call operations: List contacts
- Same example
-
Use case: Uploading resume to Job portal, client app consumes a file from REST app
- Use POST method to send file
- Use GET for download
-
Example:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>File Upload</title> </head> <body> <form action="services/fileService/upload" method="post" enctype="multipart/form-data"> <!-- split into multiple parts --> <p> File location: <input type="file" name="photo"></p> <input type="submit"/> </form> </body> </html> -
Apache CXF, Jersey can represent file content as Java Object called Attachment (Apache CXF object type)
-
To download: use
java.util.File
- POST: /fileService/upload
- GET: /fileService/download
- Project:
-
STS: restattachments
- Select Apache CXF JAX-RS dependency
-
application.properties
cxf.jars.component-scan=true server.context-path=/restattachments -
src/main/resource/static/fileupload.html (served by spring at runtime)
-
-
src/main/java/com.bharath.restws/FileService.java
import org.apache.cxf.jaxrs.ext.multipart.Attachment; @Path("/fileService") public class FileService { private static final String FILE_PATH = "/Users/bharaththippireddy/Documents/Images/uploaded/uploaded.jpg"; @Path("/upload") @POST public void upload(List<Attachment> attachments) throws FileNotFoundException, IOException { for (Attachment attachment: attachments) { copyFile(attachment.getDataHandler().getInputStream()); } } ... }
-
Service
... @Service public class FileService { ... }
-
To upload file
-
New Spring Starter Project
- Name: restattachementsclient
- Description: Rest Attachments Client
-
pom.xml
<dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-rs-client</artifactId> <version>3.2.1</version> </dependency>
-
com.bharath.restws.FileClientwith main methodWebClient client = WebClient.create("http://localhost:8080/restattachments/services/fileService/upload") // cxf class and not REST API class client.type("multiparth/form-data"); // for attachments ContentDisposition cd = new ContentDisposition("attachment;filename=MAVEN.jpg"); // tells the file name Attachement attachment = new Attachment("root", new FileInputStream(new File("/Users/bharaththippireddy/Documents/Images/MAVEN.jpg")), cd); client.post(attachment);
-
Run as Java Application
-
Open restattachments
FileService.javaSystem.out.println("==================Inside Upload=================="); -
Switch console to restattachments
-
FileService.java@GET @Path("/download") public Response download() { File file = new File(FILE_PATH); ResponseBuilder responseBuilder = Response.ok(file); responseBuilder.header("Content-Disposition", "attachment;filename=downloaded.jpg"); // file saved in this name return responseBuilder.build(); }
-
Go to web browser:
http://localhost:8080/restattachments/services/fileService/download
- Jersey is open source stack from Oracle
- Official reference implementation of JAX-RS API
- Similar to CXF
- Uses SERVLET implementation
- Implementation of JAX-RS Client API
- Custom tools
- Security
- OAuth
- ...
- Wadl generation
- Bean validation
- ...
- Security
- jersey.java.net
-
Import project
-
pom.xml
<dependencyManagement> <dependencies> <dependency> <!-- Manages versions --> <groupId>org.glassfish.jersey</groupId> <artifactId>jersey-pom</artifactId> <version>${jersey-version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-servlet-core</artifactId> </dependency> </dependencies> -
web.xml
<servlet> <servlet-name>Jersey Web Application</servlet-name> <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> <init-param> <param-name>jersey.config.server.provider.packages</param-name> <param-value>todo</param-value> <!-- scanned by jersey for endpoints --> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Jersey Web Application</servlet-name> <url-pattern>/restapi/*</url-pattern> </servlet-mapping>
-
New class:
com.bharath.trainings.jersey.MyResource@Path("/myresource") public class MyResource { @GET public String hello() { return "Hello Jersey"; } } -
Tell Jersey about the package name to scan
-
web.xml
<init-param> <param-name>jersey.config.server.provider.packages</param-name> <!-- tells jersey the end points --> <param-value>com.bharath.trainings.jersey</param-value> </init-param>
-
-
mvn clean install -
Run as > Run on Server
-
Consuming REST Service
-
New package:
com.bharath.trainings.jersey.client -
New class:
com.bharath.trainings.jersey.client.MyClientpublic static void main(String[] args) { Client newClient = ClientBuilder.newClient(); String result = client.target("http://localhost:8080/jerseyws/restapi/myresource").request().get(String.class); System.out.println(result); }
- Features:
- Spring JDBC
- Spring Messaging
- Spring ORM
- Spring MVC
- Spring REST
- Does not use JAX-RS but its own standards
@RequestMappinginstead of@Path@PathVariableinstead of@PathParam
- Does not use JAX-RS but its own standards
- App with JSON Response using Spring 4.0
- Client sends HTTP Request
- Front Controller (Dispatcher Servlet) receives the request
- Front Controller reads Handler Mappings or scans through all controller classes
- Controllers return JSON response to Client
- If Web app, controller returns view name to Dispatcher servlet and Dispatcher servlet invokes view resolver to return view
- In RESTful app, the above step is skipped
-
Download springrest app and import into Eclipse
-
pom.xml
spring-webmvc jackson-core jackson-annotations jackson-databind -
web.xml
<servlet> <servlet-name>rest</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>rest</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> -
rest-servlet.xml (
<servlet-name>-servlet.xml) - automatically searches by default- Alternative: provide context path
-
New class:
com.bharathtippireddy.trainings.controller.MyController@RestController // 4.x version, @Controller in 3.x @RequestMapping("/greeting") public class MyController { @RequestMapping(value = "/{name}", method = RequestMethod.GET) public String sayHello(@PathVariable String name) { // @ResponseBody is required for 3.x return "Hello" + name; } } -
rest-servlet.xml<context:component-scan base-package="com.bharaththippireddy.trainings.controller" /> <mvc:annotation-driven /> <!-- spring looks for annotations --> -
mvn clean install -
Run As > Run on Server
-
StockQuoteResponseclass -
MyController@RequestMapping(value = "/stockQuote/{firmName}", method = RequestMethod.GET) public StockQuoteResponse getStockQuote(@PathVariable String firmName) { StockQuoteResponse response = new StockQuoteResponse(); response.setFirmName(firmName); response.setStockValue(1000); return response; }- Jackson jars enables Spring to convert response to JSON (4.x)
- Converters in rest-servlet.xml must be defined (3.x)
-
Open from Google by grabbing URL from HOWTO.txt
-
Custom converters must be listed in spring configuration file
- CRUD operations using database tables using RESTful API
- Expose RESTful API to perform CRUD operations against real DB table
- Setup:
- Database (MySQL)
- DB table
- Spring DATA JPA (ORM)
- Hibernate
- Software setup
- Product
- ProductRepository (extends interface in Spring)
- ProductService
- ProductServiceImpl
- MySQL and MySQL Workbench (client)
- Steps:
- Download
- Install (mention Workbench)
- Configure (give root password)
- Instructions: How to Install MySQL Server 5.6 on Windows 7 Development Machine - https://corlewsolutions.xom/.../article...
-
Connect to MySQL server on MySQLWorkbench
-
Click on + for new connection
- Give connection name
local - Give root password
- Give connection name
-
Double click to open connection
-
Construct a DB:
create database mydb
use mydb;
create table product(id int, name varchar(20), description varchar(20), price int);
select * from product;
-
STS
-
File > Spring Starter Project
- Name: productcrud
- Description: Product CRUD
-
Select latest Spring boot
- Search for cxf
-
Open pom.xml
-
Add cxf dependency: search for cxf jax-rs spring boot maven
<dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-spring-boot-starter-jaxrs</artifactId> <version><latest></version> </dependency> -
Add mysql connector jar: search for mysql connector maven dependency
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version><latest></version> </dependency>
-
-
Maven > Update Project (brings the latest dependencies required)
-
Model:
Product -
Add new dependency: spring data jpa starter maven
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> -
Meven > Update project
-
Model class:
com.bharath.restws.entities.Product@Entity public class Product { @Id private int id; private String name; private String description; private int price; // getters and setters }- It is automatically serializes and deserializes
- DAO: ProductRepository
-
New interface
com.bharath.restws.repos.ProductRepositoryextendsJpaRepository(child ofCRUDRepository)public interface ProductRepository extends JpaRepository<Product, Integer> { }
-
-
New interface:
com.bharath.restws.ProductServiceList<Product> getProducts(); Product getProduct(int id); Response createProduct(Product product); // jaxrs.ws.rs.core.Response Response updateProduct(Product product); // delete next -
New class:
com.bharath.restws.ProductServiceImplimplementsProductService
@Consumes("application/json")
@Produces("application/json")
@Path("/productservice")
public interface ProductService {
@Path("/products")
@GET
List<Product> getProducts();
@Path("/products/{id}")
@GET
Product getProduct(@PathParam("id") id id);
@Path("/products")
@POST
Response createProduct(Product product);
@Path("/products")
@PUT
Response updateProduct(Product product);
}
-
ProductServiceImpl@Autowired private ProductRepository repository; @Override public List<Product> getProducts() { return repository.findAll(); } @Override public Product getProduct(int id) { return repository.findById(id).get(); // find returns Optional } @Override public Response createProduct(Product product) { Product savedProduct = repository.save(product); return Response.ok(savedProduct).build(); } @Override public Response updateProduct(Product product) { Product savedProduct = repository.save(product); // updates if product exists return Response.ok(savedProduct).build(); }
-
Data source and other spring boot properties
-
application.properties
cxf.jaxrs.classes-scan=true cxf.jaxrs.classes-scan-packages=org.codehaus.jackson.jaxrs,com.bharath.restws server.servlet.context-path=/productcrud spring.datasource.url=jdbc:mysql://localhost:3306/mydb spring.datasource.username=root spring.datasource.password=<password>
-
pom.xml
<dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-jaxrs</artifactId> <version>1.9.13</version> </dependency> <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-xc</artifactId> <version>1.9.13</version> </dependency> -
Maven > Update project
-
Run as Spring Boot Application
-
Open PostMan
-
POST: http://localhost:8080/productcrud/services/productservice/products
-
raw body
{ "id": 1, "name": "IPhone", "description": "It Rocks", "price": 1500 } -
Headers
Content-Type: application/json Accept: application/json
-
-
Check in Workbench
-
Get product
-
Another create product
-
Update product
-
PUT: http://localhost:8080/productcrud/services/productservice/products
-
raw body
{ "id": 1, "name": "IPhone", "description": "It Rocks", "price": 1000 } -
Headers
Content-Type: application/json Accept: application/json
-
-
Check in Workbench
-
Get single product
- When to use what?
- Key differences?
- HTTP Methods and Caching
- SOAP: HTTP POST for request and response
- Operations/methods are defined separately which are exposed as business logic
- REST: HTTP methods (GET, POST, PUT, DELETE)
- Cacheing is possible with GET, PUT and DELETE (because they are idempotent)
- POST cannot be cached (non idempotent) (changes state of app)
- Other requests: same response can be cached and returned
- Cacheing is possible with GET, PUT and DELETE (because they are idempotent)
- SOAP: HTTP POST for request and response
- Contract
- SOAP Contract: WSDL is contract for both operations and data
- Schema for requests and responses
- REST Contract: WADL defines HTTP Methods and URIs (no data contract)
- WADL 2.0: Data contract for RESTful services as well
- SOAP Contract: WSDL is contract for both operations and data
- WS-Standards - used to implement non-functional requirements
- SOAP: It has (out of box - no additional coding, only config) - implemented by CXF, web-sphere, web-logic (app servers)
- WS-Realiable Messages - used to send messages reliably
- WS-Transactions - to span transactions across web services
- WS-Security - secures messages
- REST: Application should handle non-functional requirements
- SOAP: It has (out of box - no additional coding, only config) - implemented by CXF, web-sphere, web-logic (app servers)
- SOAP Overhead:
- SOAP:
<soap-env>... makes handling in mobile very memory intensive - RESTP: direct messages without any envelopes
- SOAP:
- Data formats:
- SOAP: XML only
- REST: XML (for two apps integration), JSON (for exposing to UI), TEST (for reporting), ...
- Client Creation
- SOAP: WSDL2JAVA - generates clients easily (no much coding)
- REST: no such tools as of then (need to find out now)
- HTTP Methods and Caching
- When to use what?
- If there are a lot of NFRs (Security, Transactions, Reliable Messaging) - SOAP
- If a lot of apps communicate with each other
- If strict contract is required (if clients are unknown) - SOAP
- High performance and easy scalability - REST
- Cacheing can be implemented
- If there are a lot of NFRs (Security, Transactions, Reliable Messaging) - SOAP
- Today's market (as of then)
- SOAP and REST co-exist and compliment each other
- file:///Users/am/Downloads/Web-Services-Interview-Questoins-and-Answers-Bharath-Thippireddy.pdf
- https://www.udemy.com/java-web-services/learn/v4/t/lecture/6183614?start=0
- Keynote: for Mac
- Powerpoint: for Windows
- Micro Services REST APIs using Spring Data REST
- Java Web Services
- Java Web Services Part 2
- Core Java Made Easy
- Junit and Mockito Crash Course
- JDBC Servlets and JSP
- XML and XML Schema in Easy Steps
- XSLT XPATH and XQuery Fundamentals
- Maven Crash Course
- Free Java Script Fundamentals
-
JSON: JavaScript Object Notation
- For storing and exchanging data between two apps or between front end and backend
-
Easy to consume in JavaScript
-
JS Example:
var customerOrder = { customerName: "Bharath", phone: 911, items: [ laptop: "watch" ] }; customerOrder.customerName;- www.json.org: syntax description
-
Rules:
- keys in double quotes unline JS objects
-
It can replace XML (Mobile apps)
-
Implementation:
Java app serializes Java object into JSON string and sends it JavaScript de-serializes JSON string into JS object JavaScript serializes JS object into JSON string and sends it Java app de-serializes JSON string into Java object- JSON parsers serialize and de-serialize JSON
-
Example: CustomerOrder
- customerName - String
- phone - number
- items - array
-
Implementation: jsfiddle.net - can save and share
var customerOrder = { "customerName": "Bharath", "phoneNumber": 123, "items": [ "laptop" "iphone" ] } console.log(customerOrder.customerName);- Open console to see output
-
Serialization:
var jsonString = JSON.stringify(customerOrder); console.log(jsonString);- Used in AJAX
- POST body or PUT body must be string
- Used in AJAX
-
De-serialization:
var customerOrderDeSerialized = JSON.parse(jsonString); console.log(customerOrderDeSerialized.items[0]);
- WSDL for Customer Orders
- Example: CreateOrders
- CreateOrdersRequest
- customerId
- Bunch or Orders
- CreateOrdersResponse
- true/false boolean response
- CreateOrdersRequest
- Example: GetOrders
- GetOrdersRequest
- customerId
- GetOrdersResponse
- Bunch of Orders
- GetOrdersRequest
- Build WSDL Messages
- Build Operations using porttype
- Tells what is the web service capable of doing
- Binding section
- Defines WSDL binding for operations
- Service section
- Tells what URL can be used and glues everything together
- Download wsdlfirstws
- delete
src/main/WEB-INF/wsdl/CustomerOrders.wsdl
- delete
- Right click on
src/main/WEB-INF/wsdlCustomerOrders.wsdl- Namespace:
http://trainings.ws.bharath.com
- ctrl + shift + f
- Change
nametoCustomerOrdersServicein<wsdl...tag
- XML schema types
-
Two complex types: Product, Order (orderID and products)
<xsd:schema ...> <xsd:complexType name="product"> <xsd:sequence> <xsd:element name="id" type="xsd:string" /> <xsd:element name="description" type="xsd:string" /> <xsd:element name="quantity" type="xsd:integer" /> </xsd:sequence> </xsd:complexType> <xsd:complexType name="order"> <xsd:sequence> <xsd:element name="id" type="xsd:integer" /> <xsd:element name="product" type="tns:product" maxOccurs="unbounded"></xsd:element> </xsd:sequence> </xsd:complexType> </xsd:schema>
-
-
XML elements for messages
<xsd:schema ...> ... <xsd:complexType name="getOrdersRequest"> <xsd:sequence> <xsd:element name="customerId" type="xsd:integer" /> </xsd:sequence> </xsd:complexType> <xsd:complexType name="getOrdersResponse"> <xsd:sequence> <xsd:element name="order" type="tns:order" maxOccurs="unbounded" minOccurs="0"></xsd:element> </xsd:sequence> </xsd:complexType> </xsd:schema>
-
CreateOrderrequest andCreateOrderresponse<xsd:schema ...> ... <xsd:complexType name="createOrdersRequest"> <xsd:sequence> <xsd:element name="customerId" type="xsd:integer" /> <xsd:element name="order" type="tns:order" /> </xsd:sequence> </xsd:complexType> <xsd:complexType name="createOrdersResponse"> <xsd:sequence> <xsd:element name="result" type="xsd:boolean" /> </xsd:sequence> </xsd:complexType> </xsd:schema>
-
Elements that use four types
<xsd:schema ...> ... <xsd:element name="getOrdersRequest" type="tns:getOrdersRequest" /> <xsd:element name="getOrdersResponse" type="tns:getOrdersResponse" /> <xsd:element name="createOrdersRequest" type="tns:createOrdersRequest" /> <xsd:element name="createOrdersResponse" type="tns:createOrdersResponse" /> </xsd:schema>
<wsdl:message name="getOrdersRequest">
<wsdl:port element="tns:getOrdersRequest" name="parameters" />
</wsdl:message>
<wsdl:message name="getOrdersResponse">
<wsdl:port element="tns:getOrdersResponse" name="parameters" />
</wsdl:message>
<wsdl:message name="createOrdersRequest">
<wsdl:port element="tns:createOrdersRequest" name="parameters" />
</wsdl:message>
<wsdl:message name="createOrdersResponse">
<wsdl:port element="tns:createOrdersResponse" name="parameters" />
</wsdl:message>
<wsdl:portType name="CustomerOrdersPortType">
<wsdl:operation name="getOrders">
<wsdl:input message="tns:getOrdersRequest" />
<wsdl:output message="tns:getOrdersResponse" />
</wsdl:operation>
<wsdl:operation name="createOrders">
<wsdl:input message="tns:createOrdersRequest" />
<wsdl:output message="tns:createOrdersResponse" />
</wsdl:operation>
</wsdl:portType>
-
Binding connects the previously defined abstract portion to the physical portion of wsdl file
-
Binding definition
<wsdl:binding name="CustomerOrdersServiceSoapBinding" type="tns:CustomerOrdersPortType"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> <wsdl:operation name="getOrders"> <wsdl:input name="getOrdersRequest"> <soap:body use="literal" /> <!-- what is this? --> </wsdl:input> <wsdl:output name="getOrdersResponse"> <soap:body use="literal" /> </wsdl:output> </wsdl:operation> <wsdl:operation name="createOrders"> <wsdl:input name="createOrdersRequest"> <soap:body use="literal" /> </wsdl:input> <wsdl:output name="createOrdersResponse"> <soap:body use="literal" /> </wsdl:output> </wsdl:operation> </wsdl:binding>
-
Service: tells where the web service can be consumed and also connects the binding section
<wsdl:service name="CustomerOrders"> <wsdl:port binding="tns:CustomerOrdersServiceSoapBinding" name="CustomerOrderPort"> <soap:address location="http://localhost:8080/wsdlfirstws/services/customerOrdersService" /> </wsdl:port> </wsdl:service>
<wsdl:portType ...
...
<wsdl:input message="tns:getOrdersRequest" name="getOrdersResponse" />
<wsdl:output message="tns:getOrdersResponse" name="getOrdersResponse" />
...
<wsdl:input message="tns:createOrdersRequest" name="createOrdersResponse" />
<wsdl:input message="tns:createOrdersResponse" />
