How to retrieve a content of Alfresco workflow? - javascript

I have a workflow where I have audio content. I need to access for this content in other application (with javascript). I am trying with a GET method to this URL:
http://localhost:8086/alfresco/service/cmis/s/SpacesStore/i/1a7be6f8-0c50-4995-a211-1736642db06a/children?alf_ticket=TICKET_f9906d69befbc49668b92ddf372d62532a29ce7d
(In this URL, the id "1a7be6f8-0c50-4995-a211-1736642db06a" is the identificator of the package of the workflow task.)
But, the response is the next XML:
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:app="http://www.w3.org/2007/app" xmlns:cmisra="http://docs.oasis-open.org/ns/cmis/restatom/200908/" xmlns:cmis="http://docs.oasis-open.org/ns/cmis/core/200908/" xmlns:alf="http://www.alfresco.org" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/">
<author><name>admin</name></author>
<generator version="4.2.0 (r56674-b4848)">Alfresco (Community)</generator>
<icon>http://localhost:8086/alfresco/images/logo/AlfrescoLogo16.ico</icon>
<id>urn:uuid:1a7be6f8-0c50-4995-a211-1736642db06a-children</id>
<link rel="service" href="http://localhost:8086/alfresco/service/cmis"/>
<link rel="self" href="http://localhost:8086/alfresco/service/cmis/s/SpacesStore/i/1a7be6f8-0c50-4995-a211-1736642db06a/children?alf_ticket=TICKET_f9906d69befbc49668b92ddf372d62532a29ce7d"/>
<link rel="via" href="http://localhost:8086/alfresco/service/cmis/s/workspace:SpacesStore/i/1a7be6f8-0c50-4995-a211-1736642db06a"/>
<link rel="up" href="http://localhost:8086/alfresco/service/cmis/s/workspace:SpacesStore/i/13dd8d00-4ccd-4894-87fc-0b055cf41a4b/children" type="application/atom+xml;type=feed"/>
<link rel="down" href="http://localhost:8086/alfresco/service/cmis/s/workspace:SpacesStore/i/1a7be6f8-0c50-4995-a211-1736642db06a/descendants" type="application/cmistree+xml"/>
<link rel="http://docs.oasis-open.org/ns/cmis/link/200908/foldertree" href="http://localhost:8086/alfresco/service/cmis/s/workspace:SpacesStore/i/1a7be6f8-0c50-4995-a211-1736642db06a/tree" type="application/atom+xml;type=feed"/>
<title>1a7be6f8-0c50-4995-a211-1736642db06a Children</title>
<updated>2015-05-27T11:18:13.600-04:00</updated>
<opensearch:totalResults>0</opensearch:totalResults>
<opensearch:startIndex>0</opensearch:startIndex>
<opensearch:itemsPerPage>-1</opensearch:itemsPerPage>
<cmisra:numItems>0</cmisra:numItems>
</feed>
I don't know how to use this XML for my purpose. I need to hear the content (mp3 audio file) and modify its properties in my custom application.
Also I am trying with the next URL (GET):
http://localhost:8086/alfresco/service/api/node/content/workspace/SpacesStore/1a7be6f8-0c50-4995-a211-1736642db06a
But the result is: Web Script Status 404 - Not Found
How to retrieve a content of a workflow? There is some RESTful URL for this ?
Thanks for any help.
Greetings,
Pablo.

Finally, I resolve my questions using other RESTful URL. So, the steps to retrieve a content of a workflow is the next:
1. I get the package ID (this is a folder node) of the task of workflow:
GET /alfresco/service/api/task-instances/activiti$taskID
{
"data":
{
"id": "activiti$taskID",
"url": "api\/task-instances\/activiti$taskID",
"name": "wf:taskName",
"title": "Task for this",
"description": "Hello World !",
"state": "IN_PROGRESS",
"path": "api\/workflow-paths\/activiti$workflowID",
"isPooled": false,
"isEditable": true,
"isReassignable": true,
"isClaimable": false,
"isReleasable": false,
"outcome": null,
"owner":
{
"userName": "admin",
"firstName": "Admin",
"lastName": "istrator"
},
"properties":
{
"bpm_percentComplete": 0,
"bpm_description": "Hello World !",
"bpm_hiddenTransitions": [],
"bpm_package":"workspace:\/\/SpacesStore\/1a7be6f8-0c50-4995-a211-1736642db06a",
...........................................................
}
So, the package ID is: 1a7be6f8-0c50-4995-a211-1736642db06a
2. With the package ID, I get the content which I need of this package:
GET /alfresco/service/slingshot/node/workspace/SpacesStore/1a7be6f8-0c50-4995-a211-1736642db06a
.............................................
"children": [
{
"name": {
"name": "{http:\/\/www.alfresco.org\/model\/content\/1.0}grabacion1.mp3",
"prefixedName": "cm:grabacion1.mp3"
},
"nodeRef": "workspace://SpacesStore/9ed7905d-7017-40e9-9514-93244b0a9a6a",
"type": {
"name": "{http:\/\/www.alfresco.org\/model\/content\/1.0}content",
"prefixedName": "cm:content"
},
"assocType": {
"name": "{http:\/\/www.alfresco.org\/model\/bpm\/1.0}packageContains",
"prefixedName": "bpm:packageContains"
},
"primary": false,
"index": 0
}
],
.............................................
So, the content ID is: 9ed7905d-7017-40e9-9514-93244b0a9a6a
3. Finally, I get the content which I need:
GET /alfresco/service/api/node/content/workspace/SpacesStore/9ed7905d-7017-40e9-9514-93244b0a9a6a
If you need access to the properties of the content, you can use the URL of the step two with the content ID (in this example: 9ed7905d-7017-40e9-9514-93244b0a9a6a).
Greetings :)

Related

Update existing field in local json file in React Native

I'm working on an app where I have some data stored in the local JSON file. Initially, I'm showing that data using SectionList. And there are some fields to update the values of some fields of that data.
My data looks like this:
{
"title": "Terminal Settings",
"data": [
{ "title": "Keypad", "id": 1, "isSelected": false},
{ "title": "Menu", "id": 2 , "isSelected": false},
{ "title": "Tabs", "id": 3, "isSelected": false},
{ "title": "Mobile", "id": 4, "isSelected": false}
]
},
Now from UI, I want to change the status of isSelected field through the checkbox and also want to change it in the JSON file. So whenever I will access this data it should show isSelected: true.
How to do this? Do I need to use AsyncStorage for this?
I think you will definely have to open and modify the content of your file at some point, so your should need some filesystem. The best would be to simple get your json object with
const myData = require('./myDataJsonFile.json');
then modify it with for example $json[0]['data'][1]['isSelected'] = true
and finally save this in your file, replacing the file content with your $json

How to find loading bottleneck of a slow-loading SAPUI5 app

I'm building a custom SAPUI5 app which consists of a seven diagrams (sap.viz.ui5.controls.VizFrame) in the page's header content (nested inside a sap.suite.ui.commons.ChartContainer) and a grid table (sap.ui.table.Table) in the main content area. The data for the charts and the table is provided by an OData V2 Service and the app is running stand-alone on the latest version (1.81.0).
The problem is the long loading time of the app. It takes between 7 and 20 seconds. Is this common for a "more complex" app? I tried to find the bottleneck but everything looks fine. Many network requests are cached (they take 0ms), however, there is a slight delay in between them and I can't see why. Additionally, there is the following warning in the console, although I'm using the data-sap-async="true" in my index.html file:
[Deprecation] Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/. [syncXHRFix-dbg.js:211:15]
Code snippets of my index.html and manifest.json
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Loading - Customer Fact Sheet</title>
<script id="sap-ui-bootstrap"
src="resources/sap-ui-core.js"
data-sap-ui-theme="sap_fiori_3"
data-sap-ui-resourceroots='{"com.schott.fiori.customerfactsheet.customerfactsheet-fiori3": "./"}'
data-sap-ui-compatVersion="edge"
data-sap-ui-oninit="module:sap/ui/core/ComponentSupport"
data-sap-ui-async="true"
data-sap-ui-frameOptions="trusted">
</script>
<link href="https://www.schott.com/static/assets/gfx/favicon/SCHOTT_16.png" rel="shortcut icon" type="image/png" />
</head>
<body class="sapUiBody">
<div data-sap-ui-component data-name="com.schott.fiori.customerfactsheet.customerfactsheet-fiori3" data-id="container" data-settings='{"id" : "customerfactsheet-fiori3"}'></div>
</body>
</html>
{
"_version": "1.12.0",
"sap.app": {
"id": "com.schott.fiori.customerfactsheet.customerfactsheet-fiori3",
"type": "application",
"i18n": "i18n/i18n.properties",
"applicationVersion": {
"version": "1.0.0"
},
"title": "{{appTitle}}",
"description": "{{appDescription}}",
"sourceTemplate": {
"id": "servicecatalog.connectivityComponentForManifest",
"version": "0.0.0"
},
"dataSources": {
"YODATA_SD_CFS_MATRIX_SRV": {
"uri": "/sap/opu/odata/sap/YODATA_SD_CFS_MATRIX_SRV/",
"type": "OData",
"settings": {
"localUri": "localService/metadata.xml"
}
}
}
},
"sap.ui": {
"technology": "UI5",
"icons": {
"icon": "",
"favIcon": "",
"phone": "",
"phone#2": "",
"tablet": "",
"tablet#2": ""
},
"deviceTypes": {
"desktop": true,
"tablet": true,
"phone": true
}
},
"sap.ui5": {
"flexEnabled": false,
"rootView": {
"viewName": "com.schott.fiori.customerfactsheet.customerfactsheet-fiori3.view.Main",
"type": "XML",
"async": true,
"id": "Main"
},
"dependencies": {
"minUI5Version": "1.65.6",
"libs": {
"sap.ui.layout": {},
"sap.ui.core": {},
"sap.m": {}
}
},
"contentDensities": {
"compact": true,
"cozy": false
},
"models": {
"i18n": {
"type": "sap.ui.model.resource.ResourceModel",
"settings": {
"bundleName": "com.schott.fiori.customerfactsheet.customerfactsheet-fiori3.i18n.i18n"
}
},
"": {
"type": "sap.ui.model.odata.v2.ODataModel",
"settings": {
"defaultOperationMode": "Client",
"defaultBindingMode": "OneWay",
"defaultCountMode": "Request"
},
"dataSource": "YODATA_SD_CFS_MATRIX_SRV",
"preload": true
}
},
"resources": {
"css": [{
"uri": "css/style.css"
}]
},
"routing": {
"config": {
"routerClass": "sap.m.routing.Router",
"viewType": "XML",
"async": true,
"viewPath": "com.schott.fiori.customerfactsheet.customerfactsheet-fiori3.view",
"controlAggregation": "pages",
"controlId": "app",
"clearControlAggregation": false
},
"routes": [{
"name": "RouteMain",
"pattern": "RouteMain",
"target": ["TargetMain"]
}],
"targets": {
"TargetMain": {
"viewType": "XML",
"transition": "slide",
"clearControlAggregation": false,
"viewId": "Main",
"viewName": "Main"
}
}
}
},
"sap.platform.hcp": {
"uri": "webapp",
"_version": "1.1.0"
}
}
Screenshots of my network tab
As the Network tab shows, there are many modules loading sequentially one by one and many of them even via sync XHR. The most important task is to reduce sync XHRs as much as possible.
I see in the manifest.json that only a small number of libraries are declared. According to the Network tab, however, the app uses controls from other libs which aren't declared in the dependencies.
So it should be:
"sap.ui5": {
"dependencies": {
"libs": {
"sap.ui.core": {},
"sap.m": {},
"sap.ui.table": {},
"sap.f": {},
"sap.ui.unified": {},
"sap.ui.layout": {},
"sap.viz": {},
"sap.suite.ui.commons": {}
},
Some libs are required by other libs transitively (e.g. sap.ui.table requires sap.ui.unified).src You may then add "sap.ui.unified": { lazy: true } if that lib is not directly in use.
Preload thirdparty modules asynchronously beforehand that are usually loaded via loadSyncXHR.
If you inspect the Initiator column within the Network tab, you can detect more modules that are loaded via sync XHR. Adding those modules to the data-sap-ui-modules should avoid it:
<script id="sap-ui-bootstrap"
data-sap-ui-modules="sap/ui/thirdparty/datajs,sap/ui/thirdparty/require"
...>
The sap/ui/thirdparty/datajs is required by v2.ODataModel. The sap/ui/thirdparty/require module by the sap.viz library. Both modules are usually fetched via loadSyncXHR. The above snippet fixes it. You might find more such modules.
Overall, the above points should should already improve the initial loading time noticeably. For more performance guidelines, go through the Performance Checklist.
Other things to consider
I18n
In order to reduce the number of requests consider to drop the i18n-support altogether if the app targets only a certain group of people speaking the same language. Multiple requests for
i18n text bundles are not only costly in size but also blocking other requests while loading as they're also loaded via sync XHRs by default. There is a way to load them asynchronously and also specifying which locales the app supports, but that's for another topic.
OData Model
Consider to set the count mode to None if not required since $count calculations tend to be costly in the backend. Also the operation mode Client fetches all entities. Consider to lazy-load them instead.
For all aggregation bindings
"": {
"dataSource": "MyV2Source",
"settings": {
"defaultOperationMode": "Default",
"defaultCountMode": "None",
"defaultBindingMode": "TwoWay",
"preliminaryContext": true
},
"preload": true
},
About preliminaryContext: see Optimizing Dependent Bindings.
For a single aggregation binding
items: { // e.g.
path: '/MySet',
parameters: {
countMode: 'None',
operationMode: 'Client' | 'Default' | 'Server' (see API ref)
}
}
API reference: https://openui5.hana.ondemand.com/api/sap.ui.model.odata.v2.ODataListBinding
UI5 tooling
Before deploying the app, building the app via the following command should reduce the application size drastically:
ui5 build self-contained -a
From https://github.com/SAP/openui5-sample-app#option-2-self-contained-build
This is currently applicable to stand-alone apps only.

Practical ways to embed a script in a Selenium IDE .side test file?

In Selenium IDE, I want to create a page via a REST API before commencing some performance tests. I've been using executeAsyncScript to do so, but including the entire script, including the embedded page source code (twice escaped), in the tests.side JSON file, is becoming somewhat laborious whenever an edit has to be made.
Is there some way of referencing an external file or something?
I still want to do the test setup in Selenium IDE, so please do not suggest using external tools (e.g. a bash script containing a curl command) on the test environment before running the test suite.
A simplified version of my .side file is included below. What I want to change is the unmanageable nature of the value at ["tests"][0]["commands"][1]["target"].
{
"id": "00000000-0000-0000-0000-000000000000",
"version": "2.0",
"name": "tests-tests",
"url": "http://prod:1312",
"tests": [{
"id": "00000000-0000-0000-0000-000000000001",
"name": "MakeTestPage",
"commands": [{
"id": "00000000-0000-0000-0000-000000000002",
"comment": "",
"command": "open",
"target": "instructions/hcf",
"targets": [],
"value": ""
}, {
"id": "00000000-0000-0000-0000-000000000003",
"comment": "",
"command": "executeAsyncScript",
"target" : "var data = \"<body><p id=\\\"help\\\">help</p>\\r\\n</body>\" /* et cetera */",
"targets" : [],
"value" : ""
}],
"suites": [{
"id": "00000000-0000-0000-0000-000000000004",
"name": "Default Suite",
"persistSession": false,
"parallel": false,
"timeout": 300,
"tests": []
}],
"urls": ["http://prod:1312/"],
"plugins": []
}

Node ARI Client | Connect method not firing callback?

So, I've started playing with the Asterisk Restful Interface (ARI).
I have created a separate express app to do this.
I have a correctly configured instance of Asterisk 13 running. I know this because When I go to https://192.168.46.122:8088/ari/sounds in my browser, I am prompted for a username and password, which when entered, returns a valid JSON object back with the expected data...
[
{
"id": "conf-now-unmuted",
"text": "The conference is now unmuted.",
"formats": [
{
"language": "en",
"format": "gsm"
}
]
},
{
"id": "vm-nomore",
"text": "No more messages.",
"formats": [
{
"language": "en",
"format": "gsm"
}
]
},
{
"id": "vm-review",
"text": "press 1 to accept this recording press 2 to listen to it press 3 to rerecord your message",
"formats": [
{
"language": "en",
"format": "gsm"
}
]
},
{
"id": "demo-echodone",
"text": "The echo test has been completed.",
"formats": [
{
"language": "en",
"format": "gsm"
}
]
},
{
"id": "confbridge-rest-talk-vol-out",
"text": "...to reset your speaking volume to the default level.",
"formats": [
{
"language": "en",
"format": "gsm"
}
]
}, ...... etc etc
In my app.js file I have included the following code...
...
var logger = require('morgan');
var client = require('ari-client');
var url = 'https://192.168.46.122:8088/ari/sounds';
var username = 'correct_username';
var password = 'correct_password';
client.connect(url, username, password, function (err, ari) {
console.log('HELLLLLLOOOOO!!');
});
...
The issue, is that the anon callback is never fired. I never see 'HELLLLLLOOOOO!!'
Can anyone shed any light on why/under what circumstances this could happen? Are there any known bugs with the module that could be causing this?
Please let me know if you need further information about config, environment etc.
Thanks guys
UPDATE
Following comments below... I have tried the following:
client.connect(url, username, password)
.then(function(ari) {
console.log('HELLLLLLOOOOO!!');
})
.catch(function(err){
console.log('ERR: ' + err);
});
AND
client.connect(url, username, password, function (err, ari) {
if(err) console.log(err);
console.log('HELLLLLLOOOOO!!');
});
No error and no 'HELLLLLOOOOOO!!' at any point :-(
UPDATE 2
Have just visited /ari/api-docs/resources.json and got the following response... so it looks like it is present.
{
"_copyright": "Copyright (C) 2012 - 2013, Digium, Inc.",
"_author": "David M. Lee, II <dlee#digium.com>",
"_svn_revision": "$Revision: 430337 $",
"apiVersion": "1.7.0",
"swaggerVersion": "1.1",
"basePath": "http://192.168.46.122:8088/ari",
"apis": [
{
"path": "/api-docs/asterisk.{format}",
"description": "Asterisk resources"
},
{
"path": "/api-docs/endpoints.{format}",
"description": "Endpoint resources"
},
{
"path": "/api-docs/channels.{format}",
"description": "Channel resources"
},
{
"path": "/api-docs/bridges.{format}",
"description": "Bridge resources"
},
{
"path": "/api-docs/recordings.{format}",
"description": "Recording resources"
},
{
"path": "/api-docs/sounds.{format}",
"description": "Sound resources"
},
{
"path": "/api-docs/playbacks.{format}",
"description": "Playback control resources"
},
{
"path": "/api-docs/deviceStates.{format}",
"description": "Device state resources"
},
{
"path": "/api-docs/mailboxes.{format}",
"description": "Mailboxes resources"
},
{
"path": "/api-docs/events.{format}",
"description": "WebSocket resource"
},
{
"path": "/api-docs/applications.{format}",
"description": "Stasis application resources"
}
]
}
I'm now thinking it may be an SSL issue?!
Your connection is failing (for reasons outlined below), and because of an issue / upcoming-feature in node-ari-client, the failed connection is not logged.
The node-ari-client module uses Swagger, which expects to load a JSON schema describing an API. In the node-ari-client implementation, Swagger expects to find this JSON schema at %s//%s/ari/api-docs/resources.json.
So, the first thing to check is whether or not this exists / is accessible in your application:
https://192.168.46.122:8088/ari/api-docs/resources.json
There could be several reasons why this would not be available, but most likely the problem is authentication. You mention that when visiting your URL you are "prompted for a username and password". If your JSON schema (or any other files that need to be accessed without credentials) are behind authentication, you are going to need to rethink your application structure.
Currently, if there is a connection failure before Swagger has loaded the JSON schema, node-ari-client will fail silently. There is a Pull Request waiting which addresses this issue and would log the error, but in the meantime you should address the underlying issues which are preventing the connection.
If you can successfully access resources.json, there may be other issues with accessing resources. The URL you describe is accessing your service over https, but your resources.json file is telling Swagger to access it over regular http. To handle this, you could try:
Changing the basePath in your Swagger schema to use https:
"basePath": "https://192.168.46.122:8088/ari",
Adding a protocols field to your Swagger schema:
"protocols":["http", "https"]
Removing https
This is probably a good option in order to discover if https is the cause of the connection issue. Simply keep the Swagger schema exactly as is and try accessing / connecting to your services over http. Does this make a difference?

Strongloop Loopback: Filter by id of related Model

I have a Strongloop Loopback Node.js project with some models and relations.
The problem at hand
My problem relates how to query only those Media instances that have a relation to a certain Tag id, using the Angular SDK - while not querying Tags.media (which return Tag instances), but instead making a query somehow that returns plain Media instances.
Please read below for specific information..
Spec
Basically, I have a Model Media which has many 'tags' (model Tag). Think of a image file (Media) having various EXIF tags (Tag). Here is the relation spec (this all works as expected):
Media (media.json):
{
"name": "media",
"base": "PersistedModel",
"properties": {
"id": {
"type": "string",
"id": true
}
},
"relations": {
"tags": {
"type": "hasAndBelongsToMany",
"model": "tag"
}
}
Tag (tag.json):
{
"name": "tag",
"base": "PersistedModel",
"idInjection": true,
"properties": {
"name": {
"type": "string",
"required": true
}
},
"relations": {
"medias": {
"type": "hasAndBelongsToMany",
"model": "media"
}
},
"acls": [],
"methods": []
}
Solutions
Now, I know I could do a query like this (using Angular SDK in my example, but the syntax is the same):
injector.get('Tag').find({
'filter': {
'include': 'medias',
'where': {'id': <mytagid>}
}
});
My problem with this approach is, that I receive 1 (one) Tag instance with attached Media instances. This disrupts why whole workflow as I deal only with Media instances.. i just want to filter by Tag id, not bother about Tag at all.
Bottom line
If I see the API explorer (/explorer/), the return value of GET /api/tags/<myTagID>/medias is exactly what I need - an array of Media objects - but how to query them exactly like this using the Angular SDK (lb_services)?
I had a similar problem. One recommendation is to open the lb-services.js and try to find: /tags/:id/medias or something similar. Then you will find a comment like this: // INTERNAL. Use Tags.medias() instead. Or something similar. So that is the method that you should call. Do not call the "prototype$__get....." methods.
Then just call what it says there I suppose: Tag.medias({id:})
Other suggestions:
As you said in your description Media has many Tags. So why not use just
{
"name": "media",
"base": "PersistedModel",
"properties": {
"id": {
"type": "string",
"id": true
}
},
"relations": {
"tags": {
"type": "hasMany", <---------- hasMany
"model": "tag",
"foreignKey": "tagId" <---FK name
}
}
and
for the tags just belongsTo as type.
{
"name": "tag",
"base": "PersistedModel",
"idInjection": true,
"properties": {
"name": {
"type": "string",
"required": true
}
},
"relations": {
"medias": {
"type": "belongsTo",
"model": "media",
"foreignKey": "mediaId" <---FK name
}
},
"acls": [],
"methods": []
}
But really I don't think this is the problem because you said when you request GET /api/tags/<myTagID>/medias it returns what you want.
Then, in AngularJS you can use:
Media.tags({id:<mediaId>})
for media/:id/tags
and for the other side try:
Tag.medias({id:<tagId>})
Tag.find({
filter:{
where:{mediaId: <mediaId>} <----mediaId comes from FK name
}
})
In this case both are persistent models there is no problems, I had permission problems when doing a similar thing with data that extends User type. But that is another story...
Hope this is helpful, I changed some stuff from a similar app that I am doing and hope not making so many errors when adapting to your code...

Categories