Should Spring Cloud Contracts be concrete or flexible? - spring-cloud-contract

There are 2 styles of writing contracts used in our project.
First is to save both request and response as json files and use them to define a contract:
request {
body(file("request.json"))
}
response {
body(file("response.json"))
}
It creates stubs, that don't work unless your request is filled exactly like request.json, which makes it difficult to write unit tests with stubs for the consumer. However, using concrete values might be better for testing integration.
The second approach is to use regular expressions as much as possible:
request {
body([
clientName: $(anyNonBlankString()),
accountNumber: $(consumer(regex("[0-9]{20}")), producer("12345678901234567890")),
amount: $(anyNumber())
])
}
Stubs defined this way will be flexible, but we end up testing only presence of fields in the request and their format.
Which is the right way to write a contract?

It depends only on what you prefer. If you use the first option you can still use the bodyMatchers section where you can, using xpath or jspath, to define which parts of the body should be dynamic. It's all matter of preference.

Related

What is the correct JSONAPI way to post multiple related entities in a single request?

At some point in my hypothetical app, I want to create multiple related entities of different types in a single request, for efficiency sake. In the example below I serialize the request in a way that it contains the data about the new User as well as its related Avatar.
// POST /api/users
{
data: {
attributes: { ... },
type: 'user',
relationships: {
avatar: {
data: {
attributes: { ... }
type: 'avatar',
}
}
}
}
}
The question is, what would be the correct/recommended way (if there's any) to do that in JSONAPI?
Creating or updating multiple resources in a single request is not supported by JSON:API spec yet. However there is a proposal for an Atomic Operations extension for the upcoming v1.1 of the spec.
But in most cases such a feature is not required for efficiency. You might even cause more load to the server by bundling multiple create or update requests into one. Doing multiple requests in parallel is cheap with HTTP/2 nowadays.
It might not be as performant as doing it with one requests if the operations depend on each other (e.g. must await a post to be created before a comment for this post could be created). But in that case atomic transactions are also a strong requirement. That's the main driver behind that extension.
So to answer your question:
It's currently not supported in JSON:API spec.
There is a good chance that it will be supported in the next version (v1.1) by an extension.
If efficiency is the only reason you are looking for such a feature, you might not need it at all.
Since it is common, more over may times encouraged to decouple REST API resources from internal representations, there is no recommendation that would suggest against defining a specific 'virtual' endpoint, where the attributes of that resource in turn would become attributes of two or more different resources under different endpoints.
It may not solve your problem, if you want such feature in general, but if this is only needed for some resource combinations, you can always make a dedicated endpoint for a resource which incorporates all attributes of all related resources.
In your case it could be something like:
// POST /api/users_with_avatar
{
data: {
attributes: {
"user_attribute_1": "...",
"user_attribute_2": "...",
"user_attribute_3": "...",
"avatar_attribute_1": "...",
"avatar_attribute_2": "..."
},
type: 'user-with-avatar'
}
}

Custom Header with token in PASOE Business Class Entity with Web Service?

I have a PASOE Business Class Entity setup as a Web Service. I'm trying to determine how to create a custom header that will allow me to pass in a hashed token. Is this something that I need to upgrade to 11.7.4 for DOH(OpenEdge.Web.DataObject.DataObjectHandler)? Or is this something that I simply add into a method that's defined in the class? Apologies, for the lack of code to illustrate my situation, but I'm not sure where to begin.
If you're using a Business Entity with the web transport then you're using the DOH, and the below applies. If you're using the rest transport then you are not using the DOH, and are more limited in your choices.
There is doc available on the DOH at https://documentation.progress.com/output/oe117sp/index.html#page/gssp4/openedge-data-object-handler.html - it's for 11.7.4 but largely applies to all versions (that is, from 11.6.3+). This describes the JSON mapping file, which you'll need to create an override to the default, generated one.
If you want to use the header's value for all operations, then you may want to use one of the DOH's events. There's an example of event handlers at https://github.com/PeterJudge-PSC/http_samples/blob/master/web_handler/data_object_handler/DOHEventHandler.cls ; you will need to start that handler in a session startup procedure using new DOHEventHandler() (the way that code is written is that it makes itself a singleton).
You can now add handling code for the Invoking event which fires before the business logic is run.
If you want to pass the header value into the business logic you will need to
Copy the generated mapping file <service>.gen to a <service.map> , in the same folder. "gen" files are generated and will be overwritten by the tooling
In the .map file, add a new arg entry. This must be in the same order as the parameters to the BE's method.
The JSON should look something like the below. this will read the value of the header and pass it as an input parameter into the method.
{ "ablName": "<parameter_name>",
"ablType": "CHARACTER",
"ioMode": "INPUT",
"msgElem": {"type": "HEADER", "name": "<http-header-name>"}
}

Pact Contract Test :How to generate dynamic PactDslJsonBody using json value?

How to generate dynamic PactDslJsonBody using json value?
Is it possible Pact team can provide the auto builder to assign body dynamically?
Pact Body:
body(new PactDslJsonBody()
.object("testsuite")
.stringType("webId","24255")
.closeObject());
Assert Response:
"{\"testsuite\":{\"webId\":\"24255\"}}";
Based on Assert Response(as input) and create the dslbody like
String json = "{\"testsuite\":{\"webId\":\"24255\"}}"
//body(json);
body(generatePactDSLJsonBody(json));
Assert Response:
assertEqual("{\"testsuite\":{\"webId\":\"24255\"}}",json);
I know in body we can provide json itself. but i need to generate the PactDSLJson body using Json.
It is technically possible to auto-generate the DSL classes from a JSON document, but I do not see the benefit of your example. Most of the time the matchers are defined based on the semantics of the JSON payload, not the syntax.
For example, from your sample JSON, it would see the webId attribute as a string, and generate a string type matcher. However, it is clearly a number, not a string.
The auto-generated DSL body would accept the following JSON:
{"testsuite":{"webId":"This is not a web ID &^*&^%"}}
However, an auto-generation tool used to create a skeleton consumer test from a JSON document which could then be changed based on the semantics of the JSON would be really useful.
We build a library to generate the PactDslJsonBody from a Java Bean. That's not directly your use-case since you want to use JSON as input, but maybe you designed your endpoints to expose Java Beans, so you can use them for your Pacts.
You might want to have a look at https://github.com/remondis-it/pact-consumer-builder.
With this library you're able to define PactDslJsonBody mappings on a per-field or a per-type basis. In our case this reduces the boilerplate code to nearly a one-liner:
PactDslJsonBody jsonBody = ConsumerExpects.type(YOUR_BEAN_TYPE.class)
.useTypeMapping(...)
// Other field or type configurations
.build(new PactDslJsonBody(), YOUR_BEAN_SAMPLE_INSTANCE);
This performs the necessary calls on the PactDslJsonBody and you can use the result for your Pact test.
Btw: The Pact Consumer Builder library works well in conjunction with a fixture generator that produces test data instances for you Java Beans. You can use our fixture generator (https://github.com/remondis-it/resample) but every other Java Bean instance generator should work, too.

Why have a separate call to get Json?

I need to get some Json to the client side from the server and it's somewhat troublesome as almost all tutorials assume an Ajax call to a separate action to get the Json.
This led me to think that there must be some reason why it is done this way. In Asp.Net MVC we can pass a Model along with the view to get the information but we can't seem to easily pass a Json object. Instead you are supposed to make a separate call to get this information.
What if the Json info is known when the page is generated, why not generate it at the same time?
I'm sorry if I wasn't clear enough. While it's nice to hear of ways to get Json to the client, the question is actually whether there is a specific reason the Ajax call method is much more popular, like security or anything like that.
Can you put something like this into your view? (rough pseudo code, assuming using a Razor view)
< script >
var myJSON = { Field: #model.Field, Field2: #model.Field2 };
< /script >
Because you do not need both at the same time... on the first call will be to get html (the view of the data - represented by a view model), and any ajax calls will be to get the possibly updated data (json serialized view model).
No reason why you can't. You could use the javacript serializer to create a JSON string that drop on the page. You could also create an action that return the json string that you called from a script tag.
What you want if you're using KnockOut, would be the Mapping plugin that turns an ordinary JS object, like that generated above, into an observable ready for KnockOut to use. See here from info. http://knockoutjs.com/documentation/plugins-mapping.html
You can use content-negotiation by setting accept header. This is considered a best practice (and according to some RESTful).
This needs to be supported and implemented at server as well. ASP NET MVC does not make it easy to support content-negotiation and you have to implement it yourself by if-else or using ActionFilter and implementing action selector.

NHibernate.IFutureValue<> when serialized includes .Value

I'm building an ASP.NET (2.0, no, I can't change it) site with NHibernate, and have a custom JSON converter so I can not-serialize properties I want hidden from the client. This lets me just return the objects, and never have to worry about their serialized values - they're always secure.
Unfortunately, it appears that if I use query.FutureValue<class>(), the object that gets serialized is first the NHibernate.Impl.FutureValue<class> and not my entity, which means I get JSON that looks like this if I throw it in a dictionary and return it to the client:
{key: { Value: { /* my serialized object properties */ } }
Previously I discovered that I can't get any interfaces to work in ASP's JavaScriptConverter implementations... only regular or abstract classes. So returning typeof(IFutureValue<MyBaseClass>) as a supported type means my converter is completely ignored. I can catch MyBaseClass, because I refactored things earlier to use an abstract base instead of an interface, but not the interface.
And then I discover that the FutureValue implementation in .Impl is internal to the assembly, or some other such nonsense that only serves to make my .NET experience even more painful. So I can't use typeof(FutureValue<MyBaseClass>) to handle it all, because FutureValue exists only in my debugging sessions.
Is there a way to get the class type out of the assembly? Or a way to convince ASP that interfaces do in fact have uses? Or might there be some superclass I can access that would let me get around the whole issue?
Help! I like my Futures, it lets me batch a whole heck-ton of calls at once!
(if something isn't clear, or you want more code, by all means, ask! I can post quite a bit.)
If I'm understanding you correctly, it seems you are mixing things a together a little bit.
It sounds like you're trying to serialize an instance of query.FutureValue<class>(), which unsurprisingly gives you just that: a JSON object where the Value fields has JSON representing your entity.
To me it sounds like you really want to just serialize query.FutureValue<class>().Value.
Using NHibernate futures like this gives you little benefit though, so you're probably after something like:
var future1 = query1.FutureValue<SomeEntity>();
var future2 = query2.FutureValue<AnotherEntity>();
var json1 = serializer.Serialize(future1.Value); //<BAM! Multi-query gets fired!
var json2 = serializer.Serialize(future2.Value);
Does that make sense?

Resources