Getting Collection of particular Type with Hybris ModelService - interceptor

Hiy!
I want all objects(rows in Test Type) with ModelService
So I could iterate through collection and update a Single row (object)'s attribute with new value
I see getModelService.create(TestModel.class) and getModelService.save()
but will they not create a new object/row rather than update a existing object?right
I don't want to create a new one rather selecting one of the existing matching my criteria and update one attribute of that
can somebody help with List<TestModel> testModels = getModelService.get(TestModel.class) will that return me all rows (collection) of Test Type/Table?
unfortunately I can't test it so need help
Actually I am in validateInterceptor ... and on the basis of this intercepted model changed attribute value I have to update another model attribute value...
thanks

ModelService.create(new TestModel.class) will create a single instance of the specified type and attach it to the modelservice's context.
But it will only be saved to the persistence store when you call modelService.save(newInstance)
ModelService.get() returns a model object but expects a Jalo object as input, (Jalo being the legacy persistence layer of hybris) so that won't work for you.
To retrieve objects you can either write your own queries using the FlexibleSearchService or you can have a look at the DefaultGenericDao which has a bunch of simple find() type of methods.
Typically you would inject the dao like e.g.:
private GenericDao<TestModel> dao;
[...]
public void myMethod()
{
List<TestModel> allTestModels = dao.find();
[...]
}
There are a lot more methods with which you can create WHERE type of statements to restrict your result.
Regarding ValidateInterceptor:
Have a look at the wiki page for the lifecycle of interceptors:
https://wiki.hybris.com/display/release5/Interceptors
It's not a good idea to modify 'all' objects of a type while being an interceptor of that type.
So if you're in an interceptor declared for the Test item type, then don't try to modify the items there.
If you happen to be in a different interceptor and want to modify items of a different type:
E.g. you have Type1 which has a list of Type2 objects in it and in the interceptor for Type1 you want to modify all Type2 objects.
For those scenarios you would have to add the instances of Type2 that you modify to the interceptor context so that those changes will be persisted.
That would be something like:
void onValidate(Test1 model, InterceptorContext ctx) throws InterceptorException
{
...
List<Type2> type2s = dao.find();
for (Type2 type2 : type2s)
{
// do something with it
// then make sure to persist that change
ctx.registerElementFor(type2, PersistenceOperation.SAVE);
[...]
}
}

First of all - i think it's not a good idea, to create/update models in any interceptor, especially in 'validation' one.
Regarding your question:
ModelService in most of the cases works with single model, and
designed for create/update/delete operations.
To retreive all models of certain type, you have to use FlexibleSearchService
Then to update each retrieved TestType model, you can use ModelService's save method.
A query to retreive all TestType models will look like:
SELECT PK FROM {TestType}

You could simply use the Flexible Search Service search by example method, and the model service to save them all. Here is an example using Groovy script, with all products :
import java.util.List
import de.hybris.platform.core.model.product.ProductModel
import de.hybris.platform.servicelayer.search.FlexibleSearchService
import de.hybris.platform.servicelayer.model.ModelService
FlexibleSearchService fsq = spring.getBean("flexibleSearchService")
ModelService ms = spring.getBean("modelService")
ProductModel prd = ms.create(ProductModel.class)
List<ProductModel> products = fsq.getModelsByExample(prd)
//Do Whatever you want with the objects in the List
ms.saveAll(products)

Related

Dapper can't ignore nested objects for parameter?

I am beginning to use Dapper and love it so far. However as i venture further into complexity, i have ran into a big issue with it. The fact that you can pass an entire custom object as a parameter is great. However, when i add another custom object a a property, it no longer works as it tries to map the object as a SQL parameter. Is there any way to have it ignore custom objects that are properties of the main object being passed thru? Example below
public class CarMaker
{
public string Name { get; set; }
public Car Mycar { get; set; }
}
propery Name maps fine but property MyCar fails because it is a custom object. I will have to restructure my entire project if Dapper can't handle this which...well blows haha
Dapper extensions has a way to create custom maps, which allows you to ignore properties:
public class MyModelMapper : ClassMapper<MyModel>
{
public MyModelMapper()
{
//use a custom schema
Schema("not_dbo_schema");
//have a custom primary key
Map(x => x.ThePrimaryKey).Key(KeyType.Assigned);
//Use a different name property from database column
Map(x=> x.Foo).Column("Bar");
//Ignore this property entirely
Map(x=> x.SecretDataMan).Ignore();
//optional, map all other columns
AutoMap();
}
}
Here is a link
There is a much simpler solution to this problem.
If the property MyCar is not in the database, and it is probably not, then simple remove the {get;set;} and the "property" becomes a field and is automatically ignored by DapperExtensions. If you are actually storing this information in a database and it is a multi-valued property that is not serialized into a JSON or similar format, I think you are probably asking for complexity that you don't want. There is no sql equivalent of the object "Car", and the properties in your model must map to something that sql recognizes.
UPDATE:
If "Car" is part of a table in your database, then you can read it into the CarMaker object using Dapper's QueryMultiple.
I use it in this fashion:
dynamic reader = dbConnection.QueryMultiple("Request_s", param: new { id = id }, commandType: CommandType.StoredProcedure);
if (reader != null)
{
result = reader.Read<Models.Request>()[0] as Models.Request;
result.reviews = reader.Read<Models.Review>() as IEnumerable<Models.Review>;
}
The Request Class has a field as such:
public IEnumerable<Models.Review> reviews;
The stored procedure looks like this:
ALTER PROCEDURE [dbo].[Request_s]
(
#id int = null
)
AS
BEGIN
SELECT *
FROM [biospecimen].requests as bn
where bn.id=coalesce(#id, bn.id)
order by bn.id desc;
if #id is not null
begin
SELECT
*
FROM [biospecimen].reviews as bn
where bn.request_id = #id;
end
END
In the first read, Dapper ignores the field reviews, and in the second read, Dapper loads the information into the field. If a null set is returned, Dapper will load the field with a null set just like it will load the parent class with null contents.
The second select statement then reads the collection needed to complete the object, and Dapper stores the output as shown.
I have been implementing this in my Repository classes in situations where a target parent class has several child classes that are being displayed at the same time.
This prevents multiple trips to the database.
You can also use this approach when the target class is a child class and you need information about the parent class it is related to.

How to save and retrive view when it's needed

My goal is to keep session size as small as possible. (Why?.. it's other topic).
What I have is Phase listener declared in faces-config.xml
<lifecycle>
<phase-listener>mypackage.listener.PhaseListener</phase-listener>
</lifecycle>
I want to save all other views, except the last one(maximum two) , in some memcache. Getting the session map:
Map<String, Object> sessionMap = event.getFacesContext().getExternalContext().getSessionMap();
in beforePhase(PhaseEvent event) method is giving me access to all views. So here I could save all views to the memcache and delete them from the session. The question is where in jsf these views that are still loaded in the browser are requested so that I can refill with this view if it's needed. Is it possible at all? Thank you.
To address the core of your question, implement a ViewHandler, within which you can take control of the RESTORE_VIEW and RENDER_RESPONSE phases/processes. You'll save the view during the RENDER_RESPONSE and selectively restore, during the RESTORE_VIEW phase. Your view handler could look something like the following
public class CustomViewHandlerImpl extends ViewHandlerWrapper{
#Inject ViewStore viewStore; //hypothetical storage for the views. Could be anything, like a ConcurrentHashMap
ViewHandler wrapped;
public CustomViewHandlerImpl(ViewHandler toWrap){
this.wrapped = toWrap;
}
public UIViewRoot restoreView(FacesContext context, String viewId) throws IOException{
//this assumes you've previously saved the view, using the viewId
UIViewRoot theView = viewStore.get(viewId);
if(theView == null){
theView = getWrapped().restoreView(context, viewId);
}
return theView;
}
public void renderView(FacesContext context, UIViewRoot viewToRender) throws IOException, FacesException{
viewStore.put(viewToRender.getId(),viewToRender);
getWrapped().renderView(context, viewToRender);
}
}
Simply plug in your custom viewhandler, using
<view-handler>com.you.customs.CustomViewHandlerImpl</view-handler>
Of course, you probably don't want to give this treatment to all your views; you're free to add any conditions to the logic above, to implement conditional view-saving and restoration.
You should also consider other options. It appears that you're conflating issues here. If your true concern is limit the overhead associated with view processing, you should consider
Stateless Views, new with JSF-2.2. The stateless view option allows you to exclude specific pages from the JSF view-saving mechanism, simply by specifying transient="true" on the f:view. Much cleaner than mangling the UIViewRoot by hand. The caveat here is that a stateless view cannot be backed by scopes that depend on state-saving, i.e. #ViewScoped. In a stateless view, the #ViewScoped bean is going to be recreated for every postback. Ajax functionality also suffers in this scenario, because state saving is the backbone of ajax-operations.
Selectively set mark components as transient The transient property is available for all UIComponents, which means, on a per-view basis, you can mark specific components with transient="true", effectively giving you the same benefits as 1) but on a much smaller scope. Without the downside of no ViewScoped
EDIT: For some reason, UIViewRoot#getViewId() is not returning the name of the current view (this might be a bug). Alternatively, you can use
ExternalContext extCtxt = FacesContext.getCurrentInstance().getExternalContext();
String viewName = ((HttpServletRequest)extCtxt.getRequest()).getRequestURI(); //use this id as the key to store your views instead

What is the difference between Class actions and Instance actions in AngularJs?

From the docs:
Class actions return empty instance (with additional properties
below). Instance actions return promise of the action
The documentations however doesn't clearly differentiate between Class actions and Instance actions. Could you please point out differences with a good example if possible?
When you create a new resource type, you supply it a list of actions that can be performed. By default, these are get, save, query, delete, and remove (I think remove is just an alias of delete). You can add your own, as it says in the docs.
The thing about class vs instance is in regard to something it does for convenience of use. "Class actions" refers to calling the action off the resource class that you create itself, kinda like static or shared methods in some other languages. This is useful as an entry point for getting, querying, or saving an instance of your resource when you don't already have the instance. get and query are the clearest example of this. If you have a Car resource, and you need to retrieve it, where do you start? With a class action, of course, such as get.
Now, when your resource class retrieves an existing instance, or you create a new instance, $resource will extend your instance with the actions defined for your resource, but prefix them with a $ so they don't collide with fields on your resource. These are your instance actions. The difference between instance and class, is instance is done in the context of the current instance. So if you get an instance, but then call $save or $delete on that instance, it will save or delete that instance specifically. Instance actions are there simply for convenience.
So they are pretty much the same, the difference is the context in which they are being used.
function($resource) {
// first let's define a new resource for car, where all cars have an id field
// calling $resource will create a new resource class that can be used to
// create, retrieve, update, or delete instances
// this is usually done as a service and injected into controllers as needed.
var Car = $resource('/api/car/:id', {id: '#id'});
// the car class we just created has some class actions that can help you query for or get car instances
// let's create a new instance of a car and save it
var newCar = new Car({make: 'Toyota', model: 'Prius'});
// the prototype of Car includes the instance action versions of the actions defined for the resource. below, $save is your instance action
newCar.$save(); // server will respond with the object after it's saved, so we can now access the id. let's say the id it returned is 24, we'll reference this value later.
// now, let's imagine some time later we want to retrieve the car and update it
// Car.get is a class action that requests the resource from the server, parses the JSON into an object, and merges it with the Car instance prototype so you have your instance actions
// let's get the car we created previously.
// remember, this is done asynchronously, so we will do our work in a success handler that we provide to get
Car.get({id: 24}, function(myCar) {
// let's update the car now that we have it. let's set the year of the model and the color
myCar.year = 2004;
myCar.color = 'white';
// now, let's save our changes by calling the instance action $save
myCar.$save();
});
// now, let's query for all cars and get an array back
// query is a class function that expects an array of your resource to be returned
Car.query(function(cars) {
// trivial example, we're just going to enumerate the cars we found and log some info about them
for(var i = 0; i < cars.length; i++)
console.log('Found ' + cars[0].color + ' ' cars[0].year + ' ' + cars[0].make + ' ' + cars[0].model);
});
// ok, let's delete the car we created earlier. use the class action delete
Car.delete({id: 24});
}
You can technically call any actions either as a class or as an instance, but it will become obvious that some are awkward to use as instance actions and vise versa. For example, while you technically can use query as an instance action, you wouldn't do that in practice because it's extra work and it's awkward (you'd have to do new Car().$query(). That's silly. Car.query() is easier and makes more sense). So, the usage in my example above represents your normal usage.
Update:
save vs $save
$save is similar to save, but it assumes the data you want to submit during save is itself, since $save is an instance action. It is particularly useful because after the response is received, it'll update itself with the object returned by your HTTP endpoint. So if your service saves the object with some additional values populated on the server side, such as an ID, then sends the object back as JSON, $save will update the instance with the returned JSON object.
var car = new Car({make: 'Toyota', model: 'Prius'});
// at this point there is no id property, only make and model
car.$save(function() {
// angular is async, so we need a success handler to continue the explanation
// assuming your server assigned an ID and sent the resulting object back as JSON, you can now access id off the original object
console.log(car.id); // has a value now
});
You could do something similar with the class method, but it's awkward, particularly if other code in your controller needs to reference the car as you are working on it
Car.save({make: 'Toyota', model: 'Prius'}, function(car) {
// ok, we have an ID now
console.log(car.id);
});
or
var car = new Car({...});
Car.save(car, function(newCar) {
car = newCar; // wut? that's awkward
});
save could be useful during instances where you are quickly saving a small object, or are performing a sort of "fire and forget". Anyways, I rarely use save myself.

BreezeJS and Stored Procedures

I am new to BreezeJS and would like to know if there are any examples on how to use Breeze with an SQL Stored Procedure?
We have some pretty complex queries and want to be able to call them via an SP. Also, how can we tell Breeze that a column returned from a SP is the Key? We don't want to use Views, because we need to pass variables to the SP query each time we call it.
Thanks.
bob
Ok, the basic idea would be to use Breeze's EntityQuery.withParameters method to pass parameters to a server side method that calls your stored proc and returns an IEnumerable. ( i.e. the result of the stored proc).
If you want to treat this result as collection of Breeze entities then you will either need to shape the results into an existing entity type that Breeze knows about from Metadata OR manually create and add a new EntityType on the client that matches the shape that you want to return.
You may want to look at the EntityQuery.toType method to force breeze to convert your returned data into a specific EntityType or you might alternately want to use a "jsonResultsAdapter" to do the same thing.
Any data that is returned from a query and is converted into an Breeze EntityType is automatically wrapped according the "modelLibrary" in use, i.e. Knockout, Angular, Backbone etc.
If breeze is not able to construct entities out of the returned data then it will still be returned but without any special processing to wrap the result.
Hope this helps!
A sample to access Sql Stored Procedures from Breeze; the store procedure (GoStoCde) has been imported by EF.
Breeze Controller :
[HttpGet]
public object GetCdes(long jprod, int jqte, long jorder)
{
//output params
var owrk = new System.Data.Objects.ObjectParameter("wkres", typeof(string));
owrk.Value = "";
var oeror = new System.Data.Objects.ObjectParameter("ceror", typeof(int));
oeror.Value = 0;
//invoke stored procedure
var envocde = _contextProvider.Context.GoStoCde(jprod, jqte, jorder, owrk, oeror);
//stored procedure results
var cdeResult = new {
dwork = owrk.Value,
deror = oeror.Value,
};
return new { cdeResult };
}
Datacontext :
function reqLnecde(iprod, iqte, iorder, vxeror) {
logger.log("commande en cours...");
var query = new EntityQuery.from("GetCdes")
.withParameters({ jprod: iprod, jqte: iqte, jorder: iorder });
return manager
.executeQuery(query)
.then(querySucceeded)
.fail(cqueryFailed);
function querySucceeded(data) {
//stored procedure results
vxeror(data.results[0]);
//stored procedure object member value
keror = vxeror().cdeResult.deror;
if (keror === 0) {
logger.log("commande done");
} else {
logger.log("article absent");
}
}
function queryFailed(data) {
logger.log("commande failed"); //server errors
}
}
If you prefer to return entity in lieu of object, code consequently and its must also work.
Hope this helps!
Not really an answer here, just a few thoughts.
I think that the ability to return arbitrarily shaped data (read viewmodel) through the use of a stored procedure using withParameters would be an excellent way to inegerate with something like dapper.net. Upon resubmission of said viewmodel you could use the overloads to reconstruct actual entities out of your viewmodel and save changes. The only problem I have though is that one would need a way to easily and automaticaly rerun the sproc and send the data back to the client...
I would like to know if this makes sense to anyone else and/or if anyone has done it already.
For this sort of scenario I would think that you would need to disable the tracking features provided by breeze and/or write a smart enough data service that can handle the viewmodels in such a way that the javascript on the client knows when adding/removing/updating parts x,y,z of viewmodel a that you create objects jx, jy, jz (j for javascript) and submit them back and save as you go (reverse idea of what was mentioned above in a way)
Thoughts?

Dapper Correct Object / Aggregate Mapping

I have recently started evaluating Dapper as a potential replacement for EF, since I was not too pleased with the SQL that was being generated and wanted more control over it. I have a question regarding mapping a complex object in my domain model. Let's say I have an object called Provider, Provider can contain several properties of type IEnumerable that should only be accessed by going through the parent provider object (i.e. aggregate root). I have seen similar posts that have explained using the QueryMultiple and a Map extension method but was wondering how if I wanted to write a method that would bring back the entire object graph eager loaded, if Dapper would be able to do this in one fell swoop or if it needed to be done piece-meal. As an example lets say that my object looked something like the following:
public AggregateRoot
{
public int Id {get;set;}
...//simple properties
public IEnumerable<Foo> Foos
public IEnumerable<Bar> Bars
public IEnumerable<FooBar> FooBars
public SomeOtherEntity Entity
...
}
Is there a straightforward way of populating the entire object graph using Dapper?
I have a similar situation. I made my sql return flat, so that all the sub objects come back. Then I use the Query<> to map the full set. I'm not sure how big your sets are.
So something like this:
var cnn = sqlconnection();
var results = cnn.Query<AggregateRoot,Foo,Bars,FooBar,someOtherEntity,AggregateRoot>("sqlsomething"
(ar,f,b,fb,soe)=>{
ar.Foo = f;
ar.Bars = b;
ar.FooBar = fb;
ar.someotherentity = soe;
return ar;
},.....,spliton:"").FirstOrDefault();
So the last object in the Query tag is the return object. For the SplitOn, you have to think of the return as a flat array that the mapping will run though. You would pick the first return value for each new object so that the new mapping would start there.
example:
select ID,fooid, foo1,foo2,BarName,barsomething,foobarid foobaritem1,foobaritem2 from blah
The spliton would be "ID,fooid,BarName,foobarid". As it ran over the return set, it will map the properties that it can find in each object.
I hope that this helps, and that your return set is not too big to return flat.

Resources