pact-jvm testing multi tier authorization - java

I want to test my authorization-service via pact-jvm.
In my request I'm sending a html-body via post, including some metadata to verify the user - including his username and which is also sent in the header where I use Http Basic Auth. I add the header in my testclass with #TargetRequestFilter in my JUnit-Test after reading username+password from a configuration file.
This is because the application runs on different tiers. Every tier has another username+password combination. And the pact should work for every tier. Also when the user changes I only want to make little changes in my configuration file. It holds username, password, hostname, port and the protocol.
The problem is: I need to manipulate the html-body of the request depending on the content of my configuration file to match with the headers I set in my testclass without creating a new pact file every time.
So my question is: Is there a way to manipulate selective parts of the html-body I expect (via pact) from within the JUnit class?
Maybe there's another way to solve my problem I don't see yet.
Thanks in advance!
For clarity purpose an example of a Request:
<body>
<soap:envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:body>
<ns2:authevalrequest1
xmlns:ns2="http://authgroup/authBRS/specification/ServiceView/AuthProvider/authBRS/">
<inputmetadata> <version>V_1_0_0</version> <metadataentry>
<key>US</key> <value>some_username</value> </metadataentry> <metadataentry>
<key>MA</key> <value>some_user_id</value> </metadataentry> </inputmetadata>
<request> <attrs> <type>String</type> <values>
<value>some_user_id</value> </values> <xacml>urn:oasis:names:tc:xacml:1.0:subject:subject-id</xacml>
</attrs> <attrs> <type>String</type> <values> <value>00</value>
</values> <xacml>http://thisisaservice.com/resource/dataRES</xacml>
</attrs> <attrs> <type>String</type> <values> <value>abc</value>
</values> <xacml>http://thisisaservice.com/subject/authprofilename</xacml>
</attrs> <attrs> <type>String</type> <values> <value>importData</value>
</values> <xacml>http://thisisaservice.com/resource/CompanyfunctionRES</xacml> </attrs>
</request>
</ns2:authevalrequest1>
</soap:body>
</soap:envelope>
</body>
I cannot change the provider or the consumer. I'm just here to make the verification work.
Edit: Maybe I forgot to say... I want to have the response bodies matching (actual and expected), what is no problem. But I need to modify the html-body of the request depending on my config-file.

The problem here is that you're trying to do validation of XML, which Pact does not currently support out of the box as we do all our validation using JSON. What you can do is simply use a string validator or a regex validator, however, if anything in your string changes (like white space), your tests might not validate.
At this point, you're kind of on your own for creating a way to template the output into a string to validate your interactions. We have looked at supporting XML, but there's simply very little interest.

Related

what should we use SOAP and when should use REST?

When should we use SOAP and when should we use REST?
Can someone give a justifiable answer to this.
This was asked during an interview. I said it's up to contract with other parties. I don't know whether this is right or wrong. Can someone help with this.
SOAP I mean structure like below.
<?xml version='1.0' Encoding='UTF-8' ?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
<env:Header>
<m:reservation xmlns:m="http://travelcompany.example.org/reservation"
env:role="http://www.w3.org/2003/05/soap-envelope/role/next">
<m:reference>uuid:093a2da1-q345-739r-ba5d-pqff98fe8j7d</m:reference>
<m:dateAndTime>2007-11-29T13:20:00.000-05:00</m:dateAndTime>
</m:reservation>
<n:passenger xmlns:n="http://mycompany.example.com/employees"
env:role="http://www.w3.org/2003/05/soap-envelope/role/next">
<n:name>Fred Bloggs</n:name>
</n:passenger>
</env:Header>
<env:Body>
<p:itinerary xmlns:p="http://travelcompany.example.org/reservation/travel">
<p:departure>
<p:departing>New York</p:departing>
<p:arriving>Los Angeles</p:arriving>
<p:departureDate>2007-12-14</p:departureDate>
<p:departureTime>late afternoon</p:departureTime>
<p:seatPreference>aisle</p:seatPreference>
</p:departure>
<p:return>
<p:departing>Los Angeles</p:departing>
<p:arriving>New York</p:arriving>
<p:departureDate>2007-12-20</p:departureDate>
<p:departureTime>mid-morning</p:departureTime>
<p:seatPreference></p:seatPreference>
</p:return>
</p:itinerary>
</env:Body>
</env:Envelope>
In very few words, using REST you can describe the same operations you may expect from a database find, insert, update, delete. In REST such operation are paired with the HTTP command: GET, PUT, POST, DELETE. That's also why REST is referred as "state transfer" in the sense that you move objects in/out like in a database, in other words changing the state of your "model".
On the other hand SOAP reflect more a Remote Call Procedure (RPC) where, the message is heavily structured by XML, this means that in SOAP you do not simple transfer data but submit commands. In SOAP you can define, like in a programming language, methods and parameters. Regarding this last point to allow a client to use the "methods" (really are well structured XML messages, with name and parameters) defined by a SOAP service, the same service has to publish an XML document describing what messages and their format it can accept: if the method does not exists, it throws an error like "Service not supported".

Set SOAP request default values using Spring and Axis2

I don't know if this is even possible, I've been looking around and haven't found anything even related to this... or maybe I'm just not using the right terms to find it.
The problem is this.. let's say I have this request:
<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope/" soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding" xmlns:xsd="http://request.dto.webservices.com/xsd">
<soap:Header/>
<soap:Body>
<impl:testServiceMethod>
<xsd1:booleanField1>?</xsd1:booleanField1>
</impl:testServiceMethod>
</soap:Body>
</soap:Envelope>
What's currently happening is that on the back-end side the booleanField1 (which is Boolean), is received as false instead of null. To get the null I have to remove the field from the request.
Is there a way to set anywhere on the code that behavior?

FEDEX API, Authentication Failed

I am integrating FEDEX Tracking, Rate and Shipping API's into my application but i am stuck with an issue.
When i run my code with Developer account details, everything runs correctly. But when i run the same code with production keys, it gives me "Error Code 1000, Authentication Error"
I have updated all keys and also changed the URL to point to production URL "https://ws.fedex.com:443/web-services/".
It doesn't seem to be a permission issue from FEDEX end as the standard services(Tracking) are enabled by default for production and that's also giving the same error "Error Code 1000, Authentication Error".
Below is the SOAP request and response XML.
REQUEST:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header/>
<soap:Body>
<RateRequest xmlns="http://fedex.com/ws/rate/v14">
<WebAuthenticationDetail>
<UserCredential>
<Key>AAAAAAAA</Key>
<Password>BBBBBBBBB</Password>
</UserCredential>
</WebAuthenticationDetail>
<ClientDetail>
<AccountNumber>CCCCCCCC</AccountNumber>
<MeterNumber>DDDDDDDD</MeterNumber>
</ClientDetail>
<TransactionDetail>
<CustomerTransactionId>java sample - Rate Request</CustomerTransactionId>
</TransactionDetail>
<Version>
<ServiceId>crs</ServiceId>
<Major>14</Major>
<Intermediate>0</Intermediate>
<Minor>0</Minor>
</Version>
<ReturnTransitAndCommit>true</ReturnTransitAndCommit>
<RequestedShipment>
<ShipTimestamp>2015-04-19T18:21:11.542+05:30</ShipTimestamp>
<DropoffType>REGULAR_PICKUP</DropoffType>
<ServiceType>FEDEX_GROUND</ServiceType>
<PackagingType>YOUR_PACKAGING</PackagingType>
<TotalInsuredValue>
<Currency>USD</Currency>
</TotalInsuredValue>
<Shipper>
<Address>
<StreetLines>1310 Piper Dr</StreetLines>
<City>Milpitas</City>
<StateOrProvinceCode>CA</StateOrProvinceCode>
<PostalCode>95035</PostalCode>
<CountryCode>US</CountryCode>
</Address>
</Shipper>
<Recipient>
<Address>
<StreetLines>3370 E. La Palma Avenue</StreetLines>
<City>Anaheim</City>
<StateOrProvinceCode>CA</StateOrProvinceCode>
<PostalCode>92806</PostalCode>
<CountryCode>US</CountryCode>
<Residential>false</Residential>
</Address>
</Recipient>
<ShippingChargesPayment>
<PaymentType>SENDER</PaymentType>
<Payor>
<ResponsibleParty>
<AccountNumber>ACCOUNT_NUMBER_PRESENT</AccountNumber>
</ResponsibleParty>
</Payor>
</ShippingChargesPayment>
<RateRequestTypes>ACCOUNT</RateRequestTypes>
<PackageCount>1</PackageCount>
<RequestedPackageLineItems>
<GroupPackageCount>1</GroupPackageCount>
<InsuredValue>
<Currency>USD</Currency>
<Amount>100.00</Amount>
</InsuredValue>
<Weight>
<Units>LB</Units>
<Value>10</Value>
</Weight>
<Dimensions>
<Length>1</Length>
<Width>1</Width>
<Height>1</Height>
<Units>IN</Units>
</Dimensions>
<SpecialServicesRequested/>
</RequestedPackageLineItems>
</RequestedShipment>
</RateRequest>
</soap:Body>
</soap:Envelope>
RESPONSE:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<v14:RateReply xmlns:v14="http://fedex.com/ws/rate/v14">
<v14:HighestSeverity>ERROR</v14:HighestSeverity>
<v14:Notifications>
<v14:Severity>ERROR</v14:Severity>
<v14:Source>prof</v14:Source>
<v14:Code>1000</v14:Code>
<v14:Message>Authentication Failed</v14:Message>
</v14:Notifications>
<v14:TransactionDetail>
<v14:CustomerTransactionId>java sample - Rate Request</v14:CustomerTransactionId>
</v14:TransactionDetail>
<v14:Version>
<v14:ServiceId>crs</v14:ServiceId>
<v14:Major>14</v14:Major>
<v14:Intermediate>0</v14:Intermediate>
<v14:Minor>0</v14:Minor>
</v14:Version>
</v14:RateReply>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Please help me resolve this issue :(
I faced this issue from last week and found solution finally after a discussion with FedEx Technical Person.See why we are facing such error all because of Developer Test Account we generated from developer website.One thing we should keep in mind that Test Account Number start with "6" is of Production & Key Start with "5" is Correct Test Key.So Please check your Test Key when you get Authentication problem with Error Code 1000.
Revert me if this is not helpful.
https://www.xadapter.com/test-use-fedex-account-number-test-account-number-password-use/
User Account Password is different from password we have to supply in web service.
please check above link
If you're getting the error for all web services in production then you've got a key issue. Get new credentials from the developer area of FedEx or try emailing websupport at fedex.com
I struggled and so I called their support in US, which I'll say is excellent. I had a chance to speak to some developer who will observe your requests in real time and will inform you over call like what's causing this authentication issue. Call here >> 1.877.339.2774
Now as per their support person, sometime while registering multiple times the earlier generated password gets overwritten with new, while key / account & meter numbers remain the same. (test & prod key passwords are sent over email you've registered with).
So if you're sure that you're using test/production credentials correctly mentioned in your code then you try re-registering for keys and must put your direct email address on the registration form. The new password will help you get a success response from APIs.
Also, if you're using api to track a shipment, then test creds will only help if you've supplied a test tracking number, same is for production keys. Prod keys will only work for real shipment tracking IDs

Java Web Service(SOAP) Message format generic (name/value properties) nodes vs specific nodes

Need a suggestion on Java Web Service(SOAP) Message format. Thinking of two message formats.
Could you please share your thoughts on these approaches. What would you recommend?
1) Specific Message Format
Specifying the message nodes with the actual names of the data attributes like User first name , last name, ssn .... etc. see the sample below
Pros:
Message xsd will have the actual data types for the data to be propagated. This ensures the data is valid.
Cons:
Changes to the message format will lead to the xsd change which in turn lead to multiple versions of the service. this would cost the maintenance of the different versions of the service.
2) Generic Message Format
Specifying the message nodes with the name value pairs.
See the example message below.
Pros:
Additional data can be sent with additional properties wihtout changing the message format. Single version of the message can be maintained easily.
Cons:
Data is not typed and can not be validated. Service implementation needs to hard code the property names, parse the data, validate the data. Handling data with multiple values would be with some separator like comma(,). Handling the formatted data for the dates, time, currency data ... etc would be expensive.
Specific Format Message
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns1:myTestServiceOperation xmlns:ns1="http://xmlns.myenterprise.com/myenterprise/myTestWebService/types/">
<UserInfo>
<BioData>
<FirstName>John</FirstName>
<LastName>Smith</LastName>
<SSN>123-34-567</PersonNumber>
<DateOfBirth>09/01/1980</DataOfBirth>
</BioData>
<EducationalInfo>
<Qualification>Master of Science</Qualification>
<Institute>ABC</Institure>
<CourseDuration>2 Years</CourseDuration>
</EducationalInfo>
<EmploymentInfo>
<JobTile>Administrator</JobTitle>
<Employer>XYZ Corp</Employer>
<EmploymentInfo>
</UserInfo>
</ns1:myTestServiceOperation>
</soap:Body>
</soap:Envelope>
Generic Format Message
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns1:myTestServiceOperation xmlns:ns1="http://xmlns.myenterprise.com/myenterprise/myTestWebService/types/">
<Record category="BioData">
<Property name="FirstName" value="John"/>
<Property name="LastName" value="Smith"/>
<Property name="SSN" value="123-34-567"/>
</Record>
<Record category="Education">
<Property name="Qualification" value="Master of Science"/>
<Property name="Institute" value="ABC"/>
<Property name="CourseDuration" value="2 Years"/>
</Record>
<Record category="Employment">
<Property name="JobTile" value="Manager"/>
<Property name="XYZ Corp" value="XYZ Corp"/>
<Property name="CourseDuration" value="2 Years"/>
</Record>
</ns1:myTestServiceOperation>
</soap:Body>
</soap:Envelope>
Having a generic schema for a service is a bad idea, except in a handful of cases, such as response of a database query (Same service used to query different tables and different columns)
If there is probability of schema change very frequently, the consumers are affected way more than the producer. So it would be better to have multiple versions of the service running, however that requires more effort.
However, you can always use request and response transformation to have only one version of service running, here's how.
Detect the version of the incoming request (a version element on the schema should do it along with XPATH)
Use a XML transformer like Contivo to convert the incoming request to latest request version
Send this converted XML to the service to respond. Remember that you are only running the latest version of the service
Now transform the output XML to the old version, same as the request, and send back to client.
e.g.
Client sends request with schema version 1
Convert request to latest version, say 12
Send request version 12 to service
Get response version 12
Convert response version 12 to response version 1
Reply to Client with response version 1

Mechanical Turk rejects POST Requests

I'm trying to use the MTurk restful API, and POST to createHIT with a HITTypeID, however, I get the following error:
<?xml version="1.0"?>
<CreateHITResponse>
<OperationRequest>
<RequestId>199c9aff-86a4-4280-8d2f-d956a53515b0</RequestId>
</OperationRequest>
<HIT>
<Request>
<IsValid>False</IsValid>
<Errors>
<Error>
<Code>AWS.MissingParameters</Code>
<Message>Your request is missing required parameters. Required parameters include Question. Question is a required parameter. (1376962818123)</Message>
<Data>
<Key>Parameter</Key>
<Value>Question</Value>
</Data>
<Data>
<Key>Description</Key>
<Value>Question is a required parameter</Value>
</Data>
<Data>
<Key>Description</Key>
<Value>Question is a required parameter</Value>
</Data>
<Data>
<Key>Parameter</Key>
<Value>Question</Value>
</Data>
</Error>
</Errors>
</Request>
</HIT>
</CreateHITResponse>
From my understanding, title should not be required if Hittype is given. So it looks like the API is not actually viewing the POST body.
How would I work around this? Is there anything wrong with my request?
Request:
<CreateHITRequest>
<HITTypeId>HITTYPEID</HITTypeId>
<MaxAssignments>1</MaxAssignments>
<LifetimeInSeconds>604800</LifetimeInSeconds>
<Question><QuestionForm Structure></Question>
</CreateHITRequest>
You can't POST XML to Mechanical Turk over REST. It looks like you're confusing REST with SOAP to me.
Mechanical Turk's REST interface only takes URL-encoded key-value pairs, like this:
https://mechanicalturk.amazonaws.com/?Service=AWSMechanicalTurkRequester
&AWSAccessKeyId=[the Requester's Access Key ID]
&Version=2012-03-25
&Operation=CreateHIT
&Signature=[signature for this request]
&Timestamp=[your system's local time]
&HITTypeId=T100CN9P324W00EXAMPLE
&Question=[URL-encoded question data]
&LifetimeInSeconds=604800
I had mixed up the POST requests parameters.
For MTURK REST API, you do not POST the XML structure, but headers+values to the indicated URL.
Instead of URL params, you POST them as params in the POST body.
For example the GET request below:
GET https://mechanicalturk.amazonaws.com/?Service=AWSMechanicalTurkRequester
&AWSAccessKeyId=[the Requester's Access Key ID]
&Version=2012-03-25
&Operation=CreateHIT
&Signature=[signature for this request]
&Timestamp=[your system's local time]
&HITTypeId=T100CN9P324W00EXAMPLE
&Question=[URL-encoded question data]
&LifetimeInSeconds=604800
Would become:
POST https://mechanicalturk.amazonaws.com/?Service=AWSMechanicalTurkRequester
AWSAccessKeyId=[the Requester's Access Key ID]
&Version=2012-03-25
&Operation=CreateHIT
&Signature=[signature for this request]
&Timestamp=[your system's local time]
&HITTypeId=T100CN9P324W00EXAMPLE
&Question=[URL-encoded question data]
&LifetimeInSeconds=604800
Where everything below the URL is the POST body.
Hope this helps somebody.

Categories

Resources