среда, 23 сентября 2015 г.

Solving error after migrating data from Alfresco 4.2.e to Alfresco 5.0.d

Problem:


After migrating data from Alfresco 4.2.e to Alfresco 5.0.d we got the following error in the log:

 2015-09-21 17:03:32,620  ERROR [node.integrity.IntegrityChecker] [http-apr-8080-exec-1] Found 1 integrity violations:
Mandatory property not set:
   Node: workspace://SpacesStore/ca785afc-6f6a-479d-a5f2-8a737c7702b6
   Name: ca785afc-6f6a-479d-a5f2-8a737c7702b6
   Type: {http://www.alfresco.org/model/content/1.0}person
   Property: {http://www.alfresco.org/model/content/1.0}sizeCurrent
 2015-09-21 17:03:32,636  ERROR [extensions.webscripts.AbstractRuntime] [http-apr-8080-exec-1] Exception from executeScript - redirecting to status template error: 08210714 Found 1 integrity violations:
Mandatory property not set:
   Node: workspace://SpacesStore/ca785afc-6f6a-479d-a5f2-8a737c7702b6
   Name: ca785afc-6f6a-479d-a5f2-8a737c7702b6
   Type: {http://www.alfresco.org/model/content/1.0}person
   Property: {http://www.alfresco.org/model/content/1.0}sizeCurrent
 org.alfresco.repo.node.integrity.IntegrityException: 08210714 Found 1 integrity violations:
Mandatory property not set:
   Node: workspace://SpacesStore/ca785afc-6f6a-479d-a5f2-8a737c7702b6
   Name: ca785afc-6f6a-479d-a5f2-8a737c7702b6
   Type: {http://www.alfresco.org/model/content/1.0}person
   Property: {http://www.alfresco.org/model/content/1.0}sizeCurrent
        at org.alfresco.repo.node.integrity.IntegrityChecker.checkIntegrity(IntegrityChecker.java:664)
        at org.alfresco.repo.node.integrity.IntegrityChecker.beforeCommit(IntegrityChecker.java:766)
        at org.alfresco.util.transaction.TransactionSupportUtil$TransactionSynchronizationImpl.beforeCommit(TransactionSupportUtil.java:498)
        at org.springframework.transaction.support.TransactionSynchronizationUtils.triggerBeforeCommit(TransactionSynchronizationUtils.java:95)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerBeforeCommit(AbstractPlatformTransactionManager.java:925)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:738)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:724)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:475)
        at org.alfresco.util.transaction.SpringAwareUserTransaction.commit(SpringAwareUserTransaction.java:482)
        at org.alfresco.repo.transaction.RetryingTransactionHelper.doInTransaction(RetryingTransactionHelper.java:479)
        at org.alfresco.repo.web.scripts.RepositoryContainer.transactionedExecute(RepositoryContainer.java:551)
        at org.alfresco.repo.web.scripts.RepositoryContainer.transactionedExecuteAs(RepositoryContainer.java:619)
        at org.alfresco.repo.web.scripts.RepositoryContainer.executeScriptInternal(RepositoryContainer.java:399)
        at org.alfresco.repo.web.scripts.RepositoryContainer.executeScript(RepositoryContainer.java:280)
        at org.springframework.extensions.webscripts.AbstractRuntime.executeScript(AbstractRuntime.java:378)
        at org.springframework.extensions.webscripts.AbstractRuntime.executeScript(AbstractRuntime.java:209)
        at org.springframework.extensions.webscripts.servlet.WebScriptServlet.service(WebScriptServlet.java:132)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
        at org.alfresco.web.app.servlet.GlobalLocalizationFilter.doFilter(GlobalLocalizationFilter.java:61)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:504)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
        at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:421)
        at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1074)
        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611)
        at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2466)
        at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2455)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:745)

Solution:


We have fixed it by executing the script that initializes mandatory property (sizeCurrent) for user nodes:

var all = people.getPeople("");
​
for (var i=0 ; i < all.length; i++){
 
 var user = search.findNode(all[i]);
​
 if(user.properties.sizeCurrent === null){
  
  user.properties.sizeCurrent = 0;
   
  user.save();
​
 }
}

But after that I have found better solution, I haven't used it yet, but I guess it will work. Just add the following properties to alfresco-global.properties and restart Alfresco:

### Quotas ###
system.usages.enabled=true
 
### Db PostScript ###
db.schema.update=true

Original forum post of this solution.

понедельник, 7 сентября 2015 г.

How to call Alfresco from Share side

For code based on JavaScript (Surf) :

// set url to call
var url = "/url/to/some/webscript";

// get connector
var connector = remote.connect("alfresco");

// do HTTP get request
var result = connector.get(url);

// check success of call
if (result.status.code == status.STATUS_OK) {

    
    // parse response to object
    var obj = eval("(" + result.response + ")");
 
    // set some value to property of the model
    model.someProp = obj.someProp;
} else {

// do something
}


To call Alfresco from Share side in Java you need first write class:

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.extensions.surf.WebFrameworkServiceRegistry;
import org.springframework.extensions.webscripts.ScriptRemote;
import org.springframework.extensions.webscripts.connector.Response;

/**
 * Created by s.palyukh on 07.09.15.
 */
public class CallAlfresco {

    private static Log logger = LogFactory.getLog(CallAlfresco.class);

    protected WebFrameworkServiceRegistry serviceRegistry = null;

    public JSONObject jsonGet(String uri)
    {
        ScriptRemote scriptRemote = serviceRegistry.getScriptRemote();
        Response response = scriptRemote.connect().get(uri);
        if (response.getStatus().getCode() == 200)
        {
            try
            {
                return new JSONObject(response.getResponse());
            }
            catch (JSONException e)
            {
                if (logger.isErrorEnabled())
                {
                    logger.error("An error occurred when parsing response to json from the uri '" + uri + "': " + e.getMessage());
                }
            }
        }
        return null;
    }

    public void setServiceRegistry(WebFrameworkServiceRegistry serviceRegistry) {
        this.serviceRegistry = serviceRegistry;
    }
}

And then setup Spring Bean for this class:

   
      
   



пятница, 4 сентября 2015 г.

Sudo like tool for Alfresco webscripts with scope and parmeters

I want to add some notes to the following blog post:  http://fabiostrozzi.eu/2009/11/23/sudo-like-tool-for-alfresco-webscripts/. It is really useful solution, but it doesn't allow to call functions with parameters and functions from another JS object...

My implementation of Sudo class:

import org.alfresco.repo.jscript.BaseScopableProcessorExtension;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;

public class Sudo extends BaseScopableProcessorExtension {


    public Object su(final Function func) {

        final Scriptable scope = getScope();

        return su(func,scope);
    }

    public Object su(final Function func, final Scriptable scope, final Object... objects) {

        final Context cx = Context.getCurrentContext();

        AuthenticationUtil.RunAsWork&lgObject&gt raw = new AuthenticationUtil.RunAsWork&lgObject&gt() {
            public Object doWork() throws Exception {
                return func.call(cx, ScriptableObject.getTopLevelScope(scope), scope, objects);
            }
        };

        return AuthenticationUtil.runAs(raw, AuthenticationUtil.getSystemUserName());
    }
}

Initializing of Spring bean:

    
        
        
    

Using sudo service in webscripts:

var SudoExample = {

   writeToLog : function(a,b) {

      logger.getSystem().out("First parameter = " + a);
      logger.getSystem().out("Second parameter = " + a);

   },

   execute: function() {

      sudo.su(this.writeToLog,this, "param#1", "param#2");
   }
}

SudoExample.execute();

четверг, 3 сентября 2015 г.

Custom root scope object (JS API service) in Alfresco

First of all you need to know that all JS objects that we can use in webscripts or rules are based on Java. It means that when we call, for example, siteService.getSite("shortSiteName") actually performed method getSite of org.alfresco.repo.site.script.ScriptSiteService java class.

Alfresco JS API is very comfortable to use, it allows to make custom webscripts or rules really quick and integrate it to the server without restarting, but there is a problem, it doesn't cover all methods that are allowed in the Java. For example you can't disable behaviors from JS API.

To make own service that will be allowed in JS API we need to create Java class that inherits BaseScopableProcessorExtension with some public methods. For exmple:

import org.alfresco.repo.jscript.BaseScopableProcessorExtension;
import org.alfresco.repo.policy.BehaviourFilter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;

/**
 * Created by s.palyukh
 */
public class RootScopeObject extends BaseScopableProcessorExtension {

    private NamespaceService namespaceService;
    private BehaviourFilter behaviourFilter;


    public void disableBehaviour(NodeRef nodeRef, String className) {

        behaviourFilter.disableBehaviour(nodeRef, stringToQName(className));
    }

    public void enableBehaviour(NodeRef nodeRef, String className) {

        behaviourFilter.enableBehaviour(nodeRef, stringToQName(className));
    }

    public QName stringToQName(String prop) {
        return QName.resolveToQName(namespaceService, prop);
    }

    public void setNamespaceService(NamespaceService namespaceService) {
        this.namespaceService = namespaceService;
    }

    public void setBehaviourFilter(BehaviourFilter behaviourFilter) {
        this.behaviourFilter = behaviourFilter;
    }
}


And then you need to add new bean in Spring context that will have parent="baseJavaScriptExtension".

    


        
        
        




After that RootScopeObject will be allowed to use in JS with name that you have set for "extensionName" property of spring bean. For example:

customService.disableBehaviour(userhome, "cm:content");

среда, 2 сентября 2015 г.

Alfresco: Execute java code from another user


First of all you should implement RunAsWork interface from AuthenticationUtil. Do everything what you need in doWork method.
        AuthenticationUtil.RunAsWork&ltObject&gt raw = new AuthenticationUtil.RunAsWork&ltObject&gt() {
            public Object doWork() throws Exception {

                // do what you need

 
                return null;
            }
        };
Next you need to execute runAs method from AuthenticationUtil, where the first parameter is RunAsWork object and second parameter is username. In my case code from doWork method will be executed by System user.

        AuthenticationUtil.runAs(raw, AuthenticationUtil.getSystemUserName());