The references in using command services on the writeModel use this example:
const commands = {
async issue (invoice, command, { app }) {
const otherInvoice = await app.accounting.invoice(otherInvoiceId).read();
// ...
}
};
ok... what if what I need to do is really search the current or other aggregates for data? Are there filter options etc. that can be passed to read() or something to accomplish that? If not, how does one do what I'm asking?
In the write model (which is where commands are handled), an aggregate can only be referenced by its id. Hence the sample code that you provided is actually the only viable way to read an aggregate from the write model, and the read function does not have any additional arguments.
If you need to perform a search, you might want to access the read model. As in CQRS, the write and the read model should be independent of each other, it is often regarded to be a bad practice to access the read model from within the write model (among other reasons, this is primarily because of consistency issues due to eventual consistency). Hence, wolkenkit does not provide a way to access the read model from the write model.
What you might want to do instead is to perform the search from the client, before you are sending a command, and then send the desired aggregate id or ids as part of the command, so that you can then access them in the write model by their id.
I hope this helps.
Related
I'm having trouble getting my head around how to use Falcor for a particular use case.
Basically I need to take a few fields from a page and execute server side validation business logic. The page should just display whether the validation was successful or not and if not, the reason.
I could technically use a falcor get query, but they don't seem suited to multi-parameter calls
I could try and use a Falcor 'call', which would allow me to easily pass through multiple parameters, but is not suited to returning transient data.
Is this just a use case that Falcor should not really be used for or am I missing something?
All the data returned by a Falcor server is part of the model, transient or not.
A get is appropriate here because you want to read data. call are appropriate to make black box modifications to the model.
gets are always multi-parameters because you give the entire path of the data which can enclose whatever you want. Let's say we want to validate a URL. We could do something like:
getValue('updateProfileForm.website["http://example.com"].valid')
And that would return true of false depending on the URL. The result can be kept in cache eternally since it will never change (a URL is either always valid or it is not).
If the validation process needs to know the value of multiple fields at once, like password confirmation, you can do something like this:
getValue('updateProfileForm.password["new password"].confirm["new password"].valid')
If the validation depends on something external to the form, like what time it is, include this parameter in the path to maximize cache-ability.
Have all a structure for creating complex queries and obtaining data on the client side using Breeze and webapi IQueryable<T>.
I would use this structure on the client side to call another webapi controller, intercept the result of the query, and use this to make an Excel file returned by HttpResponseMessage.
See: Returning binary file from controller in ASP.NET Web API
How can I use the executeQuery without getting return data in standard Breeze JSON and without interfering with the data on the client side cache to have the 'octet-stream'.
The goal is to create an 'Export to Excel' without existing frontend paging for a large volume of data.
If you don't want to track changes, call EntityQuery.noTracking() before calling executeQuery(). This will return raw javascript objects without breeze tracking capabilities.
You can't make executeQuery() return binary 'octet-stream' data. But you can use breeze ajax implementation:
var ajaxImpl = breeze.config.getAdapterInstance("ajax");
ajaxImpl.ajax() // by default it is a wrapper to jQuery.ajax
Look http://www.breezejs.com/documentation/customizing-ajax
Create a custom "data service adapter" and specify it when you create an EntityManager for this special purpose. It can be quite simple because you disable the most difficult parts to implement, the metadata and saveChanges methods.
You don't want to cache the results. Therefore, you make sure the manager's metadata store is empty and you should add the " no caching" QueryOption. [exact names escape me as I write this on my phone].
Make sure these steps are really adding tangible value
Specialized server operations often can be performed more simply with native AJAX components.
p.s. I just saw #didar 's answer which is consistent with mine. Blend these thoughts into your solution.
This really powerful feature of grails
def save(MyDomain model) {
model.save()
render ''
}
will parse the request body or params, run MyDomain.get(id), fill in the properties from the request body or params and save. That's a lot for this little bit of code.
How do I limit the properties to bind to model? Say I have an accountBalance property that is read only and I don't want a malicious user to be able to change their account balance.
Also, I want to have multiple actions that save a different subset of properties of MyDomain... say one action could be for a bank teller user that is making a deposit for the account holder. In this case the teller should be able to set accountBalance but not password.
I realize that an actual banking app wouldn't work like this, it's just an example.
I had other problems that led me to use command objects to bind data (see Grails fails to parse request when content type is specified during post). Any solution would also have to address that post. I imagine if the solution uses command objects then it will work, but if command objects aren't in the solution, then the request body problem has to be addressed.
Have not tried on an actual domain class but can you try using bindData instead of implicitly binding where you can particularly specify which property to exclude?
def save() {
//params - A Map of source parameters
//It can be params or any other representation of request body
//request.JSON, request.XML
MyDomain model = MyDomain.get(params.id?.toLong())
bindData(model, params, [exclude: ['accountBalance']])
model.save()
render ''
}
I suggest you take a look at the documentation about binding. There is a lot of information, in particular the section about security which is similar to your concerns. Looking at the fact bindData() allows you include/exclude properties you should be able to write any variation of your binding you need.
This question isn't about REST, but about using the returned value from an invocation made in #When in the subsequent #Then.
I am looking at using JBehave to test some calls to a REST api. First there is a post to create the user
When I create a user with name Charles Darwin
As I understand REST, and this is what the Atom api does, the id is returned in the location header, e.g. /user/22. So then I want to assert something about the response.
Then user was created with a valid Id
I can do this by creating a member variable in the Steps class and storing the response there, and I have used this approach before, but is this the correct way?
Yes. One needs to store data that can be asserted on in your #Then methods. The simplest way to do this is to have a member variable - but that means that your #When/#Then need to be in the same Steps class. Another way to do it is to have a shared data object that all your Steps use and you can then set it in one method and get it in another. If you just want something generic, you can do a Map<String,? extends Object> as your generic data object. And then if you run with multiple threads, then wrap the data object in a ThreadLocal.
That's what I've seen - and the data object should be setup/cleared with a #BeforeScenario/#AfterScenario method.
I am working on a large project at work that requires me to create OData's for a large variety of Remote Function Calls. I was able to work out how to model and create OData's for simple RFCs; however, I am struggling with more complex RFCs that use multiple tables as well as simple exporting and importing parameters.
I want to output these tables as well as the importing and exporting parameters via GetEntity and GetEntitySet with just one call. I have done extensive searching online to find solutions but the best solution seems to be redefining the RFC's or calling the OData multiple times which is not ideal.
Is there any way to combine multiple tables with several entries in the output? When I say output, I am referring to the resulting XML from GetEntity/GetEntitySet.
For example, take the below fake RFC definition that takes a PERNR, and outputs a list of direct reports and a structure of employee details.
IMPORTING
PERNR
EXPORTING
S_EMPLOYEE_DETAILS
TABLES
T_DIRECT_REPORTS
Is there a way to combine the table, structure, and importing parameters into one output?
The first thing to understand is that the OData protocol is not intended to solely work like classical function calls. It is based however on entity/relationship kind of model.
So in your case id sugest to create an entity type named 'Employee' with the appropiate properties of your structure S_EMPLOYEE_DETAILS. With this you can e.g. implement the method GET_EMPLOYEE_ENTITY to retrieve a single instance of an employee via PERNR.
The next thing to do would be to get the direct reports of this employee. Since this is a relation 1:N from Employee to Employee in your case you can create a navigation property called 'DirectReports' with appropiate cardinality. Then in your GET_EMPLOYEE_ENTITYSET you can return the instances of table T_DIRECT_REPORTS (note that navigation property is not empty and you have to read the keys of the parent!).
Once you got this working you can move on to the 'best-practise' and implement the method GET_EXPANDED_ENTITY with filling the expand clauses, which is in my opinion the preferred way as you dont need to implement two seperate methods and is consiered faster as well (if many expands happen).
Both methods of implementation can be called via
GET EmployeeSet('12345678')?$expand=DirectReports