I've developed a simple webscript that accepts in input some paramenters and returns a list of workflows that matches the conditions. This is a simplified version:
WorkflowInstanceQuery workflowInstanceQuery = new WorkflowInstanceQuery();
Map<QName, Object> filters = new HashMap<QName, Object>(9);
if (req.getParameter(MY_PARAM) != null)
filters.put(QNAME_MYPROP, req.getParameter(MY_PARAM));
workflowInstanceQuery.setCustomProps(filters);
List<WorkflowInstance> workflows = new ArrayList<WorkflowInstance>();
workflows.addAll(workflowService.getWorkflows(workflowInstanceQuery));
List<Map<String, Object>> results = new ArrayList<Map<String, Object>>(workflows.size());
for (WorkflowInstance workflow : workflows)
{
results.add(buildSimple(workflow));
}
This is working perfectly, but now i'd like to have as a result all the workflows that match in like or contains the property in input.
For example if the property in input is valued "hello" i would like to have in output of the webscript the workflows that have that property with values such as "hello" or "hello Dear" or "Say hello" and so on...
This is actually working with search for content in Advanced Search of Alfresco Share...how to implement with WorkflowInstanceQuery?!
Alfresco's ActivitiWorkflowEngine class uses Activiti's HistoricProcessInstanceQuery for the search and it is using "variableValueEquals" method to add the custom properties so it will never behave as a "LIKE" clause.
There are two things which you need to consider here.Workflow Model and Content Model.You need to understand both of the things here.Whatever properties are created in content model are stored with documents and not with workflows.Workflows are having task model associated with it.So logical its going to difficult to find filter workflows based on properties of document.Because there is no association between them, unless and until you have explicitly created it.
If you want to filter based on properties than it should exist in workflow model associated with workflow task.That too you have to filter based on task of workflows.Because each task will have its own property.
Have you tried putting wildcards for your filters parameter?
filters.put(QNAME_MYPROP, "*"+req.getParameter(MY_PARAM)+"*");
Related
Somebody know how to get the last row modified from a table?
For example:
I have a Service Builder with a "Car" entity, this entity has a column called "LastModified". I want something that get the one "Car" (the last cart modified).
I don't know if create a finder with where clause is a good practice.
Thank you!
First off, service builder entities have a column called "modifiedDate" by default. Just want to make sure you're aware of that so you aren't creating redundant columns: "LastModified" and "modifiedDate".
Secondly, you could use either a custom SQL query or a dynamic query to get the Car with the most recent modifiedDate. Both approaches are documented:
https://dev.liferay.com/develop/tutorials/-/knowledge_base/6-2/developing-custom-sql-queries
https://dev.liferay.com/develop/tutorials/-/knowledge_base/6-2/leveraging-hibernates-criteria-api
Personally, I'd try the dynamic query approach (leveraging hibernate's criteria API) first. I think it's slightly simpler.
In your finder method, you could do something like this:
Order order = OrderFactoryUtil.desc("modifiedDate");
DynamicQuery carQuery = DynamicQueryFactoryUtil.forClass(Car.class).addOrder(order).setLimit(0, 1);
List<Car> cars = CarLocalServiceUtil.dynamicQuery(carQuery);
The setLimit(0, 1) limits the result of the query to only the first Car.
Broadleaf Commerce site
I need to sort the OrderItems in the cart by its product category. Currently, I am using the comparator to sort the OrderItems.
What is the best or right way to customize the default sort for Cart OrderItems?
I assume that you are currently doing something like this:
List<OrderItem> items = cart.getOrderItems();
Collections.sort(items, comparator);
and I also assume that by "default sort" you mean that you want to change the behavior when you call cart.getOrderItems().
Unfortunately, there is no way to change the behavior of the query that occurs when you call getOrderItems() as this is a JPA-generated query on the OrderItem collection within OrderImpl:
#OneToMany(mappedBy = "order", targetEntity = OrderItemImpl.class, cascade = {CascadeType.ALL})
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE, region="blOrderElements")
#AdminPresentationCollection(friendlyName="OrderImpl_Order_Items",
tab = TabName.General)
protected List<OrderItem> orderItems = new ArrayList<>();
Because of this you really only have 3 options:
Override the OrderImpl class and change the implementation of the getOrderItems() method. Unless you really needed to extend this (like to add another column to BLC_ORDER) then this isn't a great solution since it will add another table to the database that isn't actually used. See the Broadleaf extending entities tutorial. You can also technically avoid the multi-table inheritance by switching to single-table inheritance which is detailed at the bottom of that doc
Add your own query somewhere in a service method that manually queries for OrderItem for the order with a JPA query
Do what you are currently doing and sort the order items manually after retrieval with your comparator. You might consider adding a Thymeleaf utility method to have it available to you in your templates
I have a content item called Event, which has a taxonomy field called Section attached via the content definition area.
What is the easiest way to retrieve the Section field from the content within an alternate? My alternate is not overriding an Event, so Model.ContentItem is not possible. Within my alternate my Event object instance is of type ContentItem which I am retrieving through the ContentManager.
This is what i'm doing at the moment:
ContentItem content = WorkContext.Resolve<IContentManager>().Get(id);
var = content.Parts.ElementAt(13).Fields.ElementAt(0);
I realise that in the above code the index's could change, the only other way I can think of doing this is by inserting Lambda expressions in the place of the integers.
content.Parts.ElementAt(13) returns object of type ContentPart
content.Parts.ElementAt(13).Fields.ElementAt(0) returns object of type TaxonomyField. Whereas I believe I need the TermPart?
If it cannot be achieved in a simple way, why is it so difficult to perform such a simple task?
Thank you in advance.
First you do not need the ContentManager on the template.
On the Model you have the ContentItem. You can retrive the field like this:
var contentItem = Model.ContentItem;
var terms = contentItem.Event.TaxonomyFieldName.Terms;
On terms you have the terms of the ContentItem.
I'm using Sharepoint 2010's web services interface to try to get the columns for a given list. I've got not problem with getting all of the columns using a GetList() call, but the issue is that I need to only get the columns that the user can see in the List Settings view of the Sharepoint UI.
The code that I'm currently using is as follows:
rootNode = serviceReference.GetList(List_id.ToString());
Element element = XElement.Parse(rootNode.OuterXml);
var fields = from e in element.Descendants()
where e.Name.LocalName == "Field" && e.Attribute("ID") != null &&
!(e.Attribute("Name").Value.StartsWith("_") && e.Attribute("SourceID").Value == "http://schemas.microsoft.com/sharepoint/v3")
select e;
Where serviceReference is an instance of the Sharepoint Lists Service and List_id is the GUID representing the list internally to Sharepoint.
This does filter out some of the columns that I don't want, but it doesn't get rid of everything.
Does anybody know what attributes I'm looking for to narrow it down just to the ones that the user can select to be added to a view? Or am I going about this entirely the wrong way?
Many thanks for any help.
The answer to this was that I was indeed looking in the wrong place for the information I needed. As user823959 pointed out, I needed to get the content type definition and use the fields in there rather than the list itself.
To do this was a two stage process, firstly we need to get the list of content types using the Lists.GetListContentTypes method (although this takes a content type id parameter, it doesn't actually seem to matter what we put here)
XmlNode rootNode = serviceReference.GetListContentTypes(List_id.ToString(), "0×01");
The CAML returned contains the definitions for each of the content types that are available in the list - with the first content type returned being the default one (in my case, the one I was after)
String contentType = rootNode.ChildNodes[0].Attributes["ID"].Value;
Once we've got the content type that we're after we can make a call to GetListContentType with the appropriate list content type id to get the full definition of the content type:
XmlNode contentTypeNode = serviceReference.GetListContentType(List_id.ToString(), contentType);
The CAML returned from this call will contain a list of field elements that correctly show the fields that are available in the SharePoint UI's view configuration. They can be selected in a LINQ query like this:
XElement contentTypesElement = XElement.Parse(contentTypeNode.OuterXml);
var fields = from e in contentTypesElement.Descendants()
where e.Name.LocalName == "Field"
select e;
At this point, we've got a list of Field XML elements that contain information about display names, static names, content types and a whole lot more. See Microsoft's documentation on the Lists.GetListContentType page for more information on the range of information returned about each field.
Many Thanks to user823959 for pointing me in the right direction.
I am making a sharepoint state machine workflow. The first state has a "create task with content type" as the task. The content type has a field called "isApproved". I am not using any infopath forms. I am trying to get the value o fthat field to evaluate if the document is approved or not. No matter what I do I am getting "object not set to an instance of an object".
I have tried all of the following:
createTaskWithContentType1_TaskProperties1.ExtendedProperties["isApproved"].ToString();
onTaskChanged1_AfterProperties1.ExtendedProperties["isApproved"].ToString();
onTaskChanged1.AfterProperties1.ExtendedProperties["isApproved"].ToString();
What am I doing wrong???
I had similar problems once, and I had to get the field ID to access the field. This is how I did it:
Guid isApprovedFieldId = worflowProperties.TaskList.Fields["isApproved"].Id;
string approvalStatus = (string)(onTaskChanged1_AfterProperties1.ExtendedProperties[isApprovedFieldId]);
I know this answer comes too late but I figured lots of people acome accross this posting...
The field "isApproved" is a function of the infopath task form usually used by msft in example workflows. This field is certainly not available in basic content type tasks which are really just simple SharePoint task forms completely unrelated to InfoPath and the "isApproved" field. What you will need to do is grab the afterprops of the task, query the "status" field and determine if the user completed the task. If you added another column to the task called "Approved" then query that field using the taskItem["fieldName"] method and not [Extended Properties].
Hope this helps somebody!
Allen,
In addition to what Abs said. I would also recommend that you check the that the field actually exists before getting its id. Like so...
if (worflowProperties.TaskList.Fields["isApproved"] != null)
{
Guid isApprovedFieldId = worflowProperties.TaskList.Fields["isApproved"].Id;
string approvalStatus = (string)(onTaskChanged1_AfterProperties1.ExtendedProperties[isApprovedFieldId]);
}