Related
I am working on creating an AEM Workflow. One of the steps in this workflow is a Process that calls an EMCAScript file which renames the Asset if it has spaces:
var workflowData = workItem.getWorkflowData();
var pType = workflowData.getPayloadType();
if (workflowData.getPayloadType() == "JCR_PATH") {
var path = workflowData.getPayload().toString();
var parentPath = path.replace('/jcr:content/renditions/original', '');
if (workflowSession.getSession().itemExists(parentPath)) {
var replaceChars = new RegExp(" ", "g");
var node = workflowSession.getSession().getItem(parentPath);
var name = node.getPath();
var newName = name.replace(replaceChars, "_");
log.warn('Name : ' + name + ". New Name: " + newName);
if(name != newName) {
log.warn(newName);
workflowSession.getSession().move(name, newName);
node.save();
}
} else {
log.warn("Item does not exist: " + path);
}
}
The logic works as expected - the file is renamed. Other steps in the workflow seem to complete correctly as well; i.e. the thumbnail seems to be properly extracted.
However, the asset itself is "stuck" in the processing state. When I look at the failure details for the job, I see the following:
com.adobe.granite.workflow.WorkflowException: Process execution resulted in an error
at com.adobe.granite.workflow.core.job.HandlerBase.executeProcess(HandlerBase.java:201)
at com.adobe.granite.workflow.core.job.JobHandler.process(JobHandler.java:260)
at org.apache.sling.event.impl.jobs.JobConsumerManager$JobConsumerWrapper.process(JobConsumerManager.java:502)
at org.apache.sling.event.impl.jobs.queues.JobQueueImpl.startJob(JobQueueImpl.java:293)
at org.apache.sling.event.impl.jobs.queues.JobQueueImpl.access$100(JobQueueImpl.java:60)
at org.apache.sling.event.impl.jobs.queues.JobQueueImpl$1.run(JobQueueImpl.java:229)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: com.adobe.granite.workflow.WorkflowException: Failed to execute process
at com.day.cq.workflow.compatibility.CQWorkflowProcessRunner.execute(CQWorkflowProcessRunner.java:108)
at com.adobe.granite.workflow.core.job.HandlerBase.executeProcess(HandlerBase.java:191)
... 8 more
Caused by: com.day.cq.workflow.WorkflowException: execute: cannot process video, asset [{/content/dam/this file name has spaces.jpg/jcr:content/renditions/original}] in payload doesn't exist for workflow [{VolatileWorkItem_node2_var_workflow_instances_server0_2023-02-17_update_asset_58}].
at com.day.cq.dam.video.AbstractFFMpegProcess.execute(AbstractFFMpegProcess.java:75)
at com.day.cq.workflow.compatibility.CQWorkflowProcessRunner.execute(CQWorkflowProcessRunner.java:93)
... 9 more
I understand the error: the Workflow cannot find the original file since it has been moved/renamed. However, what I don't understand is why I am receiving that error from the "FFmpeg thumbnails" step when it is before the step (Process near the bottom) that does the renaming.
Is it possible to update the payload (Jcr Path) so that all steps in the Workflow see the updated name? I am using Adobe AEM 6.5.10.
I have tried many various ways to insert data (see the // comments). But still it doesn't seem to insert the data in either chromium or firefox (with ubuntu).
Full example:
`
<!doctype html>
<html><head>
<meta charset="UTF-8">
<script type = "text/javascript" src="jquery-1.11.0.js"></script>
<script type = "text/javascript" src="jquery.indexeddb.js"></script>
</head><body><script type = "text/javascript">
var key = null;
// Simply open the database once so that it is created with the required tables
$.indexedDB("BibleWay", {
"schema": {
"1": function(versionTransaction){
var catalog = versionTransaction.createObjectStore("context", {
keyPath: 'keyPath', autoIncrement: true
});
catalog.createIndex("bid");
catalog.createIndex("bk");
catalog.createIndex("c");
catalog.createIndex("v");
catalog.createIndex("t");
},
}
}).done(function(){
// Once the DB is opened with the object stores set up, show data from all tables
window.setTimeout(function(){
downloadCatalog();
}, 200);
});
function downloadCatalog(){
$.getJSON("3.json", function(data){
$.indexedDB("BibleWay").transaction("context").then(function(){
console.log("Transaction completed, all data inserted");
// loadFromDB("catalog");
}, function(err, e){
console.log("Transaction NOT completed", err, e);
}, function(transaction){
var catalog = transaction.objectStore("context"),$doadd,i2=0;;
catalog.clear();
/*$.each(data, function(i){
_(catalog.add(this));
})*/
$.each(data, function( index, value ) {
// bible id [bid]
var split_bid=index;
$.each(value, function( index, value ) {
// bible book name
var split_bk=index;
$.each(value, function( index, value ) {
// bible book chapter
var split_c=index;
$.each(value, function( index, value ) {
//var $doadd={"bid":split_bid,"bk":split_bk,"c"=split_c ,"v"=index,"t"=value};
//$doadd="{bid:\""+split_bid + "\",bk:\"" + split_bk + "\",c=" + split_c + ",v=" + index + ",t=\"" + value+"\"}";
$doadd=new Object();
$doadd.bid=split_bid;
$doadd.bk=split_bk;
$doadd.c=split_c;
$doadd.v=index;
$doadd.t=value;
catalog.add($doadd);
if (i2<10) {
console.log($doadd);
++i2;
}
//catalog.add(JSON.stringify($doadd));
//catalog.add({bid:split_bid,bk:split_bk,c:split_c,v:index,t:value});
//console.log(split_bid + " " + split_bk + " " + split_c + " " + index + ": " + value );
})
})
})
});
})
}
);
}
//$.indexedDB("BibleWay").deleteDatabase();
</script></body></html>
`
The JSON file "3.json":
{"3":{"GEN":{"1":{"1":"In the begynnynge God created heaven and erth."}}}}
Console Messages:
XHR finished loading: "http://host.host/3.json". jquery-1.11.0.js:9666
Object {bid: "3", bk: "GEN", c: "1", v: "1", t: "In the begynnynge God created heaven and erth."}
Transaction completed, all data inserted.
I found a bug in the jquery indexeddb api first that i fixed by commenting the line 90:
//e.name = "exception";
dfd.rejectWith(idbRequest, ["exception", e]);
This test is based on the code found in this example: http://nparashuram.com/jquery-indexeddb/example/
Thank you for your help
It's important and common for a library to surface any underlying errors, so if you've got some error messages or other warnings please update your answer to include them. I am wondering in particular whether your transaction has autocommited before the write was attempted.
I'm not too familiar with this API, but I see a common antipattern in that you are chaining your store creation and data insertion. Unless your jQuery library has designed around this common pattern, you could be running into that trouble here.
In IDB all action happens in a transaction. When you create modify anything related to a store or index you need what in IDB parlance is called a versionchange event. While such a transaction is capable of writing, reading and modifying schema, a phenomena us developers notice is that it ends up "autocommiting" despite your best attempts to keep it alive using closures, which maintain a reference to the commit and thereby should (I believe) keep it from commiting.
In case that's the problem, I suggest you decompose your callback hell into smaller helldoms: one for the object store, one for the object insertion. What this tends to do is create two closures around your versionchange and readwrite transactions and makes sure each operation completes successfully.
first off : I'm new to node, and a relative programming beginner.
I'm trying to create a small web app with Express, whose only goal is to fetch and reformat data from a website that doesn't have an open API.
To do so, I've decided to learn about scraping, and that brought me to Cheerio and Request.
I'm using reddit as an example, to learn on. The end goal in this example is to gather the name and href of the posts on the front page as well as the url leading to the comments, then to go on that page to scrape the number of comments.
What follows is the route that is called on a GET request to / (please excuse the variable names, and the comments/console.logs, I got frustrated) :
/*
* GET home page.
*/
exports.index = function(req, res){
var request = require('request')
, cheerio =require('cheerio')
, mainArr = []
, test = "test"
, uI
, commentURL;
function first() {
request("http://www.reddit.com", function(err, resp, body) {
if (!err && resp.statusCode == 200) {
var $ = cheerio.load(body);
$('.thing', '#siteTable').each(function(){
var url = $('a.title', this).attr('href')
, title = $('a.title', this).html()
, commentsLink = $('a.comments', this).attr('href')
, arr = [];
arr.push(title);
arr.push(url);
arr.push(commentsLink);
mainArr.push(arr);
});
second();
};
});
}
function second() {
for (i = mainArr.length - 1; i >= 0; i--) {
uI = mainArr[i].length - 1;
commentURL = mainArr[i][uI];
console.log(commentURL + ", " + uI + ", " + i);
var foo = commentURL;
request(foo, function(err, resp, body) {
console.log("what the shit");
// var $ = cheerio.load(body);
// console.log(mainArr.length + ", " + commentURL + ", " + i + ", " + uI);
// var test = $('span.title', 'div.content').html();
console.log(test + ", "+ foo + ", " + commentURL + ", " + i + ", " + uI);
// mainArr[1][2] = test;
});
};
if (i<=0) {
res.render('index', {title: test});
};
}
first();
};
The function first(); works as intended. It puts the title, the href and url to the comments in an array, then pushes that array in a master array containing those data points for all of the posts on the front page. It then calls the function second();
Said function's goal is to loop through the master array (mainArr[]), then select all of the urls leading to comments (mainArr[i][uI]) and launch a request() with that url as first parameter.
The loop works, but during the second call of request() inside the second() function, everything breaks down. The variable i gets set permanently at -1, and commentURL (the variable that is set to the URL of the comments of the current post), is defined permanently as the first url in arrMain[]. There are also weird behaviors with arrMain.length. Depending on where I place it, it tells me that arrMain is undefined.
I have a feeling that I'm missing something obvious (probably to do with asynchronicity), but for the life of me, I can't find it.
I would be really greatful for any suggestions!
You are correct about your guess, it's the infamous "Javascript loop Gotcha". See here, for example, for an explanation:
Javascript infamous Loop issue?
Besides that, it seems that only your debug prints are affected. The commented code regarding var test ought to work.
Finally, the kind of language is frowned upon in SO, you would do well to take 2 minutes and change your variable names in this post.
Thanks to #asgoth, I am able to use AngularJS $http service to retrieve stock prices from Yahoo as described here: Cannot read response from AngularJS $resource JSONP get from Yahoo Finance
In the "getHistoricalPrice" function, it puts the price inside an array, which is inside an object. From inside that function, I am able to access the price and write it to console.
The function returns the object to where it is called from. From there, I can successfully write the entire object out to console. However, I cannot access the elements of this object. I tried many different ways, but still cannot access the data in the object. You can see the code at http://jsfiddle.net/curt00/LTazR/2/ or below:
angular.module('app', ['ngResource']);
function AppCtrl($scope, $http, $resource) {
var historical_price = getHistoricalPrice("AAPL", 'start date is hard coded', 'end date is hard coded');
console.log("after calling historical price: ", historical_price); // historical_price is an object and all of the correct data is outputted to console here, but I cannot access its elements directly from Javascript.
for(var key in historical_price) {
console.log("key =",key); // this outputs "key = list"
}
console.log("after calling getHistoricalPrice: ", historical_price.list[0][1]); // Cannot access this as browser console gives error: TypeError: Cannot read property '1' of undefined
console.log("after calling getHistoricalPrice: ", historical_price['list'][0][1]); // Cannot access this as browser console gives error: TypeError: Cannot read property '1' of undefined
console.log("after calling getHistoricalPrice: ", historical_price[0][1]); // Cannot access this as browser console gives error: TypeError: Cannot read property '1' of undefined
function getHistoricalPrice(symbol, start, end) {
var query = 'select * from csv where url=\'http://ichart.yahoo.com/table.csv?s=' + symbol + '&a=' + '11' + '&b=' + '19' + '&c=' + '2012' + '&d=' + '11' + '&e=' + '19' + '&f=' + '2012' + '&g=d&ignore=.csv\'';
var url = 'http://query.yahooapis.com/v1/public/yql?q=' + fixedEncodeURIComponent(query) + '&format=json&callback=JSON_CALLBACK';
var histData = {};
$http.jsonp(url, {timeout: 30000}).success(function(json) {
var list = [];
var result = json.query.results.row;
result.shift(); // remove the header (columns) row
angular.forEach(result, function(row) {
list.push([(new Date(row.col0)).getTime()/1000, parseFloat(row.col4)]);
});
list.sort(function(val1, val2) {
return val1[0] - val2[0];
});
histData.list = list;
console.log('Loaded historical data',histData.list[0][1],', for ' + symbol); // This works and gives the price
});
return histData;
}
var fixedEncodeURIComponent = function(str) {
return encodeURIComponent(str).replace(/[!'()]/g, escape).replace(/\*/g, "%2A");
};
}
Any help or suggestions to solve this problem is greatly appreciate!
It's a matter of timing.
In lines 12-14 you are trying to access histData.list before it has been populated. This is because this code is run before the success callback to the $http.jsonp function is executed.
Any code that depends on that callback being completed must be in the callback or in a function called in the callback.
See my answer on https://stackoverflow.com/a/13967709/1916258
A great way to debug the Yahoo api is using the YQL Console: http://developer.yahoo.com/yql/console/
Info about the different posibilities (which stock info) can be found on http://www.gummy-stuff.org/Yahoo-data.htm
Edit: there was still a problem with function fixedEncodeURIComponent. It should encode quotes (") too:
var fixedEncodeURIComponent = function(str) {
return encodeURIComponent(str).replace(/[!'()]/g, escape).replace(/\*/g, "%2A").replace(/\"/g, "%22");
};
BobS is right, you aren't timing things correctly. Also you declared fixedEncodeURIComponent after you had called it. This was resulting in an immediate error when I loaded up the jsfiddle.
While you were passing the callback through to your function correctly, you weren't actually calling it. I stripped out all the post processing of the json as you have some other errors involving the query and just implemented the callback so you can see it working.
After the request is finished and you're still in the success function you need to add
if(typeof(callback) === "function"){
callback();
}
This calls that function you passed in and runs it. Here is a working jsFiddle of it:
http://jsfiddle.net/LTazR/22/
I also updated a new variable i created call output so you can see it changing.
Thanks to everybody for providing suggestions.
I solved the problem by using AngularJS' $scope variable, such as $scope.symbol[user].price. I created this variable before calling the getHistoricalPrice function and then in that function, after the result is returned from $http.jsonp, I put the value into the $scope variable, as such:
$scope.symbol[user].price = row.col4;
I am currently working with Alfresco 4.0.d community edition (I also tried this on Alfresco 4.0.c community edition) on a Oracle Linux 6 64bit virtual machine, using Firefox as my browser.
Most recently, I had been attempting to create a script which could be executed via a rule that would dynamically create sub-folders as new items entered a space/folder.
Essentially, say you have a newly created piece of content called fileOne. This file will sit in a space called mainFolder, and when a rule is run on the file to execute a script, the script will look to see if sub-folders exist based on the title and author values of the file. If not, it will create sub-folders within that mainFolder based on the title value --> sub-folder, and author value --> sub-sub-folder of that file. And then I want that content/file to be moved over to that either that existing or newly created sub-sub folder.
Ultimately I want something that looks like:
Space: mainFolder
|---> Content: fileOne --> Properties: Name, Title, Author
|---> Space: Title
|---> Space: Author
|---> Content: fileOne --> Properties: Name, Title, Author
Below is the script...
function main()
{
//mainFolder space/folder MUST exist under companyhome.
var rootSpaceName = companyhome.childByNamePath("mainFolder");
if(rootSpaceName == null)
{
logger.log("Company Home/mainFolder does not exist, so we have nothing to do.");
return;
}
else
{
logger.log("Company Home/mainFolder exists, so carry on our process.");
var childList = rootSpaceName.children;
var count = childList.length;
var seconds = new Date().getTime() / 1000;
if(count == 0)
{
logger.log("Company Home/mainFolder does not have child, nothing to do.");
return;
}
else
{
for(var i = 0; i < count; i++)
{
// File Title MUST exist.
var childTitle = childList[i].properties.title;
if(childTitle == null)
{
childTitle = "New Title " + seconds;
}
// File Author MUST exist.
var childAuthor = childList[i].properties.author;
if(childAuthor == null)
{
childAuthor = "New Author " + seconds;
}
var child = childList[i];
logger.log("This child is: " + child);
if(child.isContainer == false)
{
for(var j = 0; j < count; j++)
{
var newChildName = childList[j].properties.name;
logger.log("New child name: " + newChildName);
var newChild = childList[j];
if((newChild.isContainer == true) && (childTitle == newChildName))
{
var newSpaceName = rootSpaceName.childByNamePath(newChildName);
var newChildList = newSpaceName.children;
var newCount = newChildList.length;
for(var k = 0; k < newCount; k++)
{
var newNewChildName = newChildList[k].properties.name;
var newNewChildAuthor = newChildList[k].properties.author;
var newNewChild = newChildList[k];
if((newNewChild.isContainer == true) && (newNewChildAuthor == childAuthor))
{
var currentSpace = newSpaceName.childByNamePath(newNewChildName);
child.move(currentSpace);
}
}
}
else
{
// If title folder is already created, not need to create again.
var newSpaceName = companyhome.childByNamePath("mainFolder/" + childTitle);
if(newSpaceName == null)
{
newSpaceName = rootSpaceName.createFolder(childTitle);
logger.log("mainFolder/" + childTitle + " is created.");
}
// If author folder is already created, not need to create again.
var newNewSpaceName = companyhome.childByNamePath("mainFolder/" + childTitle + "/" + childAuthor);
if(newNewSpaceName == null)
{
newNewSpaceName = newSpaceName.createFolder(childAuthor);
logger.log("mainFolder/" + childTitle + "/" + childAuthor + " is created.");
}
child.move(newNewSpaceName);
logger.log("Moving file " + child.properties.name);
}
}
}
}
}
}
return;
}
main();
So to test this, step-by-step here is what I do:
I click on Company Home.
I click on Create, Create Space.
I then create a space called mainFolder (this is under Company Home).
I then click on the newly created folder, then click on More Actions, Manage Content Rules.
Then I click on Create Rule.
5a. Where it tells me to select a condition, I choose All Items, then I click Add to List, then I hit Next.
5b. Where it now tells me to select an action, I choose Execute Script, then I click Set Values and Add, which allows me to choose the script called new-create-folders.js which I had previously added to the Scripts folder within the Data Dictionary. Then I click OK, and then Next.
5c. Here where it asks me for the type, I choose Items are updated. I then enter a title like create folders rule. And finally I check Run rule in the background, then I hit Next.
5d. Now I click Finish to finalize my rule.
Now with the rule created, I click Create, Create Content.
6a. I give my content a name like name001, then I hit Next, then I enter a title like title001 and an author like author001. Then I hit OK.
What happens now has got me confused; it creates one sub folder called title001 like I wanted it to, and within that sub-folder it creates another folder called author001, and within that folder the file called name001 has been moved. And that is sort of how I want it to work, but there are still problems. Under the mainFolder, there is also a new sub-folder called New Title 1346102873.393 New Title 1346102873.393 with a folder inside of that called New Author 1346102873.393, but there is no file inside of that folder. And I don't know why this folder is created when I only added one piece of content to the mainFolder? Also, now that the folders have been created, the rule also looks to have been deleted from the mainFolder, i.e. there are no longer any rules applied to the folder. And when I go back to create the rule again on the mainFolder, I get the error: Failed to create Rule due to error: null. And below are the errors I get in the log files...
Output/Errors from Alfresco Log
17:27:51,373 DEBUG [org.alfresco.repo.jscript.RhinoScriptProcessor] Imports resolved, adding resource '_root
17:27:53,389 DEBUG [org.alfresco.repo.jscript.ScriptLogger] Company Home/mainFolder exists, so carry on our process.
17:27:53,400 DEBUG [org.alfresco.repo.jscript.ScriptLogger] This child is: Node Type: {http://www.alfresco.org/model/content/1.0}systemfolder, Node Aspects: [{http://www.alfresco.org/model/content/1.0}auditable, {http://www.alfresco.org/model/system/1.0}referenceable, {http://www.alfresco.org/model/system/1.0}localized]
17:27:53,400 DEBUG [org.alfresco.repo.jscript.ScriptLogger] New child name: b8ea2cb0-6fb6-481e-bb7b-d5364d9c509e
17:27:53,422 DEBUG [org.alfresco.repo.jscript.ScriptLogger] mainFolder/New Title 1346102873.393 is created.
17:27:53,439 DEBUG [org.alfresco.repo.jscript.ScriptLogger] mainFolder/New Title 1346102873.393/New Author 1346102873.393 is created.
17:27:53,498 DEBUG [org.alfresco.repo.jscript.ScriptLogger] Moving file b8ea2cb0-6fb6-481e-bb7b-d5364d9c509e
17:27:53,499 DEBUG [org.alfresco.repo.jscript.ScriptLogger] New child name: name001
17:27:53,523 DEBUG [org.alfresco.repo.jscript.ScriptLogger] Moving file b8ea2cb0-6fb6-481e-bb7b-d5364d9c509e
17:27:53,524 DEBUG [org.alfresco.repo.jscript.ScriptLogger] This child is: Node Type: {http://www.alfresco.org/model/content/1.0}content, Node Aspects: [{http://www.alfresco.org/model/content/1.0}auditable, {http://www.alfresco.org/model/system/1.0}referenceable, {http://www.alfresco.org/model/content/1.0}titled, {http://www.alfresco.org/model/content/1.0}author, {http://www.alfresco.org/model/system/1.0}localized, {http://www.alfresco.org/model/application/1.0}inlineeditable]
17:27:53,524 DEBUG [org.alfresco.repo.jscript.ScriptLogger] New child name: b8ea2cb0-6fb6-481e-bb7b-d5364d9c509e
17:27:53,534 DEBUG [org.alfresco.repo.jscript.ScriptLogger] mainFolder/title001 is created.
17:27:53,546 DEBUG [org.alfresco.repo.jscript.ScriptLogger] mainFolder/title001/author001 is created.
17:27:53,561 DEBUG [org.alfresco.repo.jscript.ScriptLogger] Moving file name001
17:27:53,561 DEBUG [org.alfresco.repo.jscript.ScriptLogger] New child name: name001
17:27:53,577 DEBUG [org.alfresco.repo.jscript.ScriptLogger] Moving file name001
17:27:53,578 DEBUG [org.alfresco.repo.jscript.RhinoScriptProcessor] Time to execute script: 1976.9988ms
17:31:13,385 ERROR [org.alfresco.web.ui.common.Utils] Failed to create Rule due to error: null
java.lang.NullPointerException
at org.alfresco.repo.rule.RuleServiceImpl.getLinkedToRuleNode(RuleServiceImpl.java:1516)
at org.alfresco.repo.rule.RuleServiceImpl.isLinkedToRuleNode(RuleServiceImpl.java:1504)
at org.alfresco.repo.rule.RuleServiceImpl.checkForLinkedRules(RuleServiceImpl.java:947)
at org.alfresco.repo.rule.RuleServiceImpl.saveRule(RuleServiceImpl.java:740)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.alfresco.repo.security.permissions.impl.AlwaysProceedMethodInterceptor.invoke(AlwaysProceedMethodInterceptor.java:34)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.alfresco.repo.security.permissions.impl.ExceptionTranslatorMethodInterceptor.invoke(ExceptionTranslatorMethodInterceptor.java:46)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.alfresco.repo.audit.AuditMethodInterceptor.invoke(AuditMethodInterceptor.java:147)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy53.saveRule(Unknown Source)
at org.alfresco.web.bean.rules.CreateRuleWizard.finishImpl(CreateRuleWizard.java:148)
at org.alfresco.web.bean.dialog.BaseDialogBean$1.execute(BaseDialogBean.java:123)
at org.alfresco.web.bean.dialog.BaseDialogBean$1.execute(BaseDialogBean.java:119)
at org.alfresco.repo.transaction.RetryingTransactionHelper.doInTransaction(RetryingTransactionHelper.java:388)
at org.alfresco.web.bean.dialog.BaseDialogBean.finish(BaseDialogBean.java:129)
at org.alfresco.web.bean.wizard.WizardManager.finish(WizardManager.java:593)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.myfaces.el.MethodBindingImpl.invoke(MethodBindingImpl.java:132)
at org.apache.myfaces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:61)
at javax.faces.component.UICommand.broadcast(UICommand.java:151)
at javax.faces.component.UIViewRoot._broadcastForPhase(UIViewRoot.java:115)
at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:191)
at org.apache.myfaces.lifecycle.InvokeApplicationExecutor.execute(InvokeApplicationExecutor.java:32)
at org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:105)
at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:80)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:143)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.alfresco.repo.web.filter.beans.SessionSynchronizedFilter.doFilter(SessionSynchronizedFilter.java:67)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.alfresco.web.app.servlet.AuthenticationFilter.doFilter(AuthenticationFilter.java:104)
at sun.reflect.GeneratedMethodAccessor443.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.alfresco.repo.management.subsystems.ChainingSubsystemProxyFactory$1.invoke(ChainingSubsystemProxyFactory.java:116)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy238.doFilter(Unknown Source)
at org.alfresco.repo.web.filter.beans.BeanProxyFilter.doFilter(BeanProxyFilter.java:82)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.alfresco.repo.web.filter.beans.NullFilter.doFilter(NullFilter.java:68)
at sun.reflect.GeneratedMethodAccessor443.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.alfresco.repo.management.subsystems.ChainingSubsystemProxyFactory$1.invoke(ChainingSubsystemProxyFactory.java:116)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy238.doFilter(Unknown Source)
at org.alfresco.repo.web.filter.beans.BeanProxyFilter.doFilter(BeanProxyFilter.java:82)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.alfresco.web.app.servlet.GlobalLocalizationFilter.doFilter(GlobalLocalizationFilter.java:58)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:470)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:857)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Thread.java:662)
Does anyone know why that additional folder is being created, as well as why the rule is being deleted after it executes on the newly created piece of content, and why I cannot add a new rule to the folder after it first deletes the original rule?
I posted the answer to this exact question from the same poster in the Alfresco forums. The answer is that the code attempts to create a folder using the same name as the document. Nodes must be uniquely named in a folder so this is not allowed.
It sounds like your rule is running multiple times and is tripping over itself. Could it be that some of the actions that the script itself is performing causes it to be run again?
Check that your rule is not being applied to sub-folders, and rather than selecting 'All Items' in the condition part of the wizard, try something more specific, e.g. all content items.
The problem actually I think should be that the rule is triggered multiple times, by the condition rule "All Items" are being updated. So EVERY node receive an update in the repository, inside the space with the rule (maybe also the sub-folder, I'd check that), it triggers, and creates probably a loop.
Have you tried to use a rule with the trigger "when node are being created"?
UPDATE:
So, i've tried to debug this on Alfresco 3.4.7 Enteprise and 4.0 Community x64 both (Linux AND Windows).
I've created a js file named inside Scripts directory inside
Alfresco, /Company Home/Data Dictionary.
Then I created a folder mainFolder inside the Company Home space.
I uploaded a new PDF file inside the folder mainFolder.
Then i executed the fs file against the PDF file. So, entering into the detailed view of the document, and then clicking on "Run Action" - "Execute Script".
There, everything works perfectly!
So in the end, the problem is in the rule execution, that trigger on "All items" so, it recursively triggers when the script creates the new folder with title name.
I tried to execute rule with the "only PDF type" nodes, and it works like a charm!
Hope this helps...
May be your requirement is
files which are existed in mainFolder have title and author fields.
you want to move your files into title->author folder.
Like that
mainFolder
-> FileName: file1, Title: title1, Author: author1
to
mainFolder
-> title1
->author1
->file1
I try your code edited with my own and run in alfresco community 4.0c in alfresco side and with java script console in share side in windows both.
When creating rule to mainFolder
1) Select Conditions
1.1 Content of type or sub-type as select conditons
1.2 Content as Set condition values, not check the checkbox below
Summary is Item is a subtype of 'Content'
2) Select Actions
Execute Script same as you
3) Type
Items are created or inserted
I choose these because running our code dynamically creates folders.
So rule is only applied for contents. Others are same as you except uncheck execute rule in background. If item created has no title name, alfresco default assumed item name as title.
Last updated code :
function main()
{
//mainFolder space/folder MUST exist under companyhome.
var rootSpaceName = companyhome.childByNamePath("mainFolder");
if(rootSpaceName == null)
{
logger.log("Company Home/mainFolder does not exist, so we have nothing to do.");
return;
}
else
{
logger.log("Company Home/mainFolder exists, so carry on our process.");
var childList = rootSpaceName.children;
var count = childList.length;
if(count == 0)
{
logger.log("Company Home/mainFolder does not have child, nothing to do.");
return;
}
else
{
for(var i = 0; i < count; i++)
{
var child = childList[i];
logger.log("This child is: " + child);
// If each of child is file
if(child.isDocument)
{
// Get title of file and
// If childTitle is null, we set DEFAULT value
var childTitle = childList[i].properties.title;
if(childTitle == null)
{
childTitle = "New Title";
}
else if(childTitle == child.properties.name)
{
childTitle = "Title " + childTitle;
}
// Get author of file.
// If childAuthor is null, we set DEFAULT value
var childAuthor = childList[i].properties.author;
if(childAuthor == null)
{
childAuthor = "New Author";
}
logger.log("Original Title :" + child.properties.title + "\tAuthor :" + child.properties.author);
logger.log("Setting Title :" + childTitle + "\tAuthor :" + childAuthor);
// If title folder does not exist, create title folder
var newSpaceTitle = companyhome.childByNamePath("mainFolder/" + childTitle);
if(newSpaceTitle == null)
{
newSpaceTitle = rootSpaceName.createFolder(childTitle);
logger.log("mainFolder/" + childTitle + " is created.");
}
// If author folder does not exist, create author folder
var newSpaceAuthor = companyhome.childByNamePath("mainFolder/" + childTitle + "/" + childAuthor);
if(newSpaceAuthor == null)
{
newSpaceAuthor = newSpaceTitle.createFolder(childAuthor);
logger.log("mainFolder/" + childTitle + "/" + childAuthor + " is created.");
}
child.move(newSpaceAuthor);
logger.log("Moving file " + child.properties.name);
}
}
}
}
return;
}
main();
The line:
var rootSpaceName = companyhome.childByNamePath("mainFolder");
will try to locate a folder relative to companyhome i.e. the root of the repository. Does that folder exist in your repository?
If you are trying to write a script that operates on files entering a space, then don't you need to use paths relative to that file or space (using the document or space objects, not companyhome)?
If not, perhaps you could explain a little more what you are trying to achieve?
If you are not already using it, then the Alfresco JavaScript Console is an extremely useful add-on for trying out JavaScript code, and you can see console output using logger.log().