cancel
Showing results for 
Search instead for 
Did you mean: 

Creating Users and Groups Programmatically

joaotpd
Champ on-the-rise
Champ on-the-rise
Hi all!!

I'm trying to create users and groups programmatically… For this I'm using the Alfresco Developer Guide Example:

BootstrapAuthorityCreator.java

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import javax.transaction.UserTransaction;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.security.AuthorityType;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService;
import org.apache.log4j.Logger;

public class BootstrapAuthorityCreator {
   
    private AuthorityService authorityService;
    private PersonService personService;
    private TransactionService transactionService;
    private AuthenticationService authenticationService;
    private UserTransaction tx;
    private static Logger logger = Logger.getLogger(BootstrapAuthorityCreator.class);

    public void init() throws Exception {

       String salesGroup;
       String marketingGroup;
      
       tx = transactionService.getUserTransaction();
        tx.begin();
       
       // create tuser1, tuser2, tuser3, tuser4
        if(!authenticationService.authenticationExists("tuser1")) {
          authenticationService.createAuthentication("tuser1", "password".toCharArray());
          if (logger.isDebugEnabled()) logger.debug("Created tuser1 auth");
        }

        if (!personService.personExists("tuser1")) {
          personService.createPerson(createDefaultProperties("tuser1", "Test", "User1", "tuser1@localhost", "password"));
          if (logger.isDebugEnabled()) logger.debug("Created tuser1 person");
       }

        if(!authenticationService.authenticationExists("tuser2")) {
          authenticationService.createAuthentication("tuser2", "password".toCharArray());
          if (logger.isDebugEnabled()) logger.debug("Created tuser2 auth");
        }

       if (!personService.personExists("tuser2")) {
          personService.createPerson(createDefaultProperties("tuser2", "Test", "User2", "tuser2@localhost", "password"));
          if (logger.isDebugEnabled()) logger.debug("Created tuser2 person");
       }

        if(!authenticationService.authenticationExists("tuser3")) {
          authenticationService.createAuthentication("tuser3", "password".toCharArray());
          if (logger.isDebugEnabled()) logger.debug("Created tuser3 auth");
        }

       if (!personService.personExists("tuser3")) {
          personService.createPerson(createDefaultProperties("tuser3", "Test", "User3", "tuser3@localhost", "password"));
          if (logger.isDebugEnabled()) logger.debug("Created tuser3 person");
       }

        if(!authenticationService.authenticationExists("tuser4")) {
          authenticationService.createAuthentication("tuser4", "password".toCharArray());
          if (logger.isDebugEnabled()) logger.debug("Created tuser4 auth");
        }

       if (!personService.personExists("tuser4")) {
          personService.createPerson(createDefaultProperties("tuser4", "Test", "User4", "tuser4@localhost", "password"));
          if (logger.isDebugEnabled()) logger.debug("Created tuser4 person");
       }
       
       if (authorityService.authorityExists(authorityService.getName(AuthorityType.GROUP, "sales"))) {
          salesGroup = authorityService.getName(AuthorityType.GROUP, "sales");
       } else {
          // create the sales group
          salesGroup = authorityService.createAuthority(AuthorityType.GROUP, null, "sales");
       }

       //add tuser1 and tuser2 to the sales group
       authorityService.addAuthority(salesGroup, "tuser1");
       authorityService.addAuthority(salesGroup, "tuser2");
       
       if (authorityService.authorityExists(authorityService.getName(AuthorityType.GROUP, "marketing"))) {
          marketingGroup = authorityService.getName(AuthorityType.GROUP, "marketing");
       } else {
          // create the marketing group
          marketingGroup = authorityService.createAuthority(AuthorityType.GROUP, null, "marketing");
       }

       //add tuser3 and tuser4 to the marketing group
       authorityService.addAuthority(marketingGroup, "tuser3");
       authorityService.addAuthority(marketingGroup, "tuser4");
       
       tx.commit();
    }
   
    private Map<QName, Serializable> createDefaultProperties(String userName, String firstName, String lastName,
            String email, String password) {
        HashMap<QName, Serializable> properties = new HashMap<QName, Serializable>();
        properties.put(ContentModel.PROP_USERNAME, userName);
        properties.put(ContentModel.PROP_FIRSTNAME, firstName);
        properties.put(ContentModel.PROP_LASTNAME, lastName);
        properties.put(ContentModel.PROP_EMAIL, email);
        properties.put(ContentModel.PROP_PASSWORD, password);
        return properties;
    }

   public void setAuthorityService(AuthorityService authorityService) {
      this.authorityService = authorityService;
   }

   public void setPersonService(PersonService personService) {
      this.personService = personService;
   }

   public void setTransactionService(TransactionService transactionService) {
      this.transactionService = transactionService;
   }

   public void setAuthenticationService(AuthenticationService authenticationService) {
      this.authenticationService = authenticationService;
   }
}

module-context.xml

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>

<beans>

    <!– A simple class that is initialized by Spring –>
    <bean id="sdk.createUsers.createUsersBean" class="org.alfresco.module.sdkcreateusers.BootstrapAuthorityCreator" init-method="init">
        <property name="personService">
            <ref bean="personService" />
        </property>
        <property name="authorityService">
            <ref bean="authorityService" />
        </property>
        <property name="transactionService">
            <ref bean="transactionService" />
        </property>       
        <property name="authenticationService">
            <ref bean="authenticationService" />
        </property>       
    </bean>
</beans>

but this doesn't seem to work… I'm getting this error:

(…)
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sdk.createUsers.createUsersBean' defined in file [/opt/alfresco/tomcat/webapps/alfresco/WEB-INF/classes/alfresco/module/sdkCreateUsers/module-context.xml]: Invocation of init method failed; nested exception is java.lang.NullPointerException
Caused by: java.lang.NullPointerException
        at org.alfresco.repo.search.IndexerComponent.createNode(IndexerComponent.java:72)
        at org.alfresco.repo.node.index.NodeIndexer.indexCreateNode(NodeIndexer.java:91)
        at org.alfresco.repo.node.db.DbNodeServiceImpl.createNode(DbNodeServiceImpl.java:345)
        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:304)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
        at org.alfresco.repo.transaction.SingleEntryTransactionResourceInterceptor.invokeInternal(SingleEntryTransactionResourceInterceptor.java:163)
        at org.alfresco.repo.transaction.SingleEntryTransactionResourceInterceptor.invoke(SingleEntryTransactionResourceInterceptor.java:138)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
        at $Proxy9.createNode(Unknown Source)
        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:304)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
        at org.alfresco.repo.tenant.MultiTNodeServiceInterceptor.invoke(MultiTNodeServiceInterceptor.java:110)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
        at $Proxy9.createNode(Unknown Source)
        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.alfresco.repo.service.StoreRedirectorProxyFactory$RedirectorInvocationHandler.invoke(StoreRedirectorProxyFactory.java:221)
        at $Proxy10.createNode(Unknown Source)
        at org.alfresco.repo.node.MLPropertyInterceptor.invoke(MLPropertyInterceptor.java:279)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
        at org.alfresco.repo.node.NodeRefPropertyMethodInterceptor.invoke(NodeRefPropertyMethodInterceptor.java:188)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
        at org.alfresco.repo.node.NodeRefPropertyMethodInterceptor.invoke(NodeRefPropertyMethodInterceptor.java:188)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
        at $Proxy9.createNode(Unknown Source)
        at org.alfresco.repo.security.authentication.RepositoryAuthenticationDao.createUser(RepositoryAuthenticationDao.java:254)
        at org.alfresco.repo.security.authentication.AuthenticationServiceImpl.createAuthentication(AuthenticationServiceImpl.java:82)
        at org.alfresco.repo.security.authentication.AbstractChainingAuthenticationService.createAuthentication(AbstractChainingAuthenticationService.java:76)
        at org.alfresco.module.sdkcreateusers.BootstrapAuthorityCreator.init(BootstrapAuthorityCreator.java:35)
        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.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeCustomInitMethod(AbstractAutowireCapableBeanFactory.java:1242)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1208)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1172)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:427)
        at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:249)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:155)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:246)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:160)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:291)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:352)
        at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:246)
        at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:189)
        at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:49)
        at org.alfresco.web.app.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:69)
        at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3843)
        at org.apache.catalina.core.StandardContext.start(StandardContext.java:4342)
        at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
        at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
        at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)
        at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:627)
        at org.apache.catalina.startup.HostConfig.deployDescriptors(HostConfig.java:553)
        at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:488)
        at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1149)
        at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311)
        at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
        at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
        at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
        at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
        at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
        at org.apache.catalina.core.StandardService.start(StandardService.java:516)
        at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
        at org.apache.catalina.startup.Catalina.start(Catalina.java:578)
        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.catalina.startup.Bootstrap.start(Bootstrap.java:288)
        at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
15:50:19,065 INFO  [org.alfresco.web.site.FrameworkHelper] Successfully Initialized Web Framework
(…)

Can someone please tell me what I'm doing wrong??
I'm deploying the .amp in alfresco-community-tomcat-3.2…
Thanks!!

João Duarte
2 REPLIES 2

indiemusic
Champ in-the-making
Champ in-the-making
I am new to Alfresco. I also keen to know how to Programmatically add groups, aka.. the above question..

Thanks in advance …

ferbru60
Champ in-the-making
Champ in-the-making
I think the best is to use the Alfresco REST API.

With PERL for example you can do that (and much more) :

#########################################################
# Classe Alfresco
# Auteur :    Bruno Ferrari - Grenoble INP
# Date :     14/10/2009
# Version :    1.0a
#########################################################

package    Alfresco;

require    Exporter;


our @ISA    = qw(Exporter);
our @EXPORT    = qw
    (
        new
        login
        logout
        errorCode
        errorMessage
        dumpPersonInfos
        getAllPersons
        searchPersons
        createPerson
        deletePerson
        getPersonInfos
        setPersonInfos
        dumpGroupInfos
        createGroup
        deleteGroup
        getAllRootGroups
        getAllGroups
        searchGroups
        getGroupInfos
        getGroupDirectMembers
        getGroupDirectPersons
        getGroupDirectSubGroups
        addPersonToGroup
        removePersonFromGroup
        addSubGroupToGroup
        removeSubGroupFromGroup
    );
#our @EXPORT_OK;
our $VERSION    = "1.0a";


use warnings;
use strict;

### Variables et fonctions
use HTTP::Request::Common;
use HTTP::Request;
use HTTP::Response;
use HTTP::Headers;
use LWP::UserAgent;

use JSON;


#—————————————————————————
sub new
{
    my ($class, $host, $port) = @_;
   

    my $self = { _rp => undef, _verbose => 0 };
    bless $self, $class;
    $self->{_rp} = $self;
    $self->{_host} = $host;
    $self->{_port} = $port;
    $self->{_errorCode} = 0;
    $self->{_errorMsg} = '';
    return $self;
}

#—————————————————————————
sub login ()
{
    my ($self, $username, $password) = @_;

    my $host = $self->{_host};
    my $port = $self->{_port};
    my $ua = LWP::UserAgent->new;
    my $h = HTTP::Headers->new;
    $h->header ('Content-Type' => 'application/json', Accept=>'application/json');
    my $GetReq = HTTP::Request->new
        (
            'POST',
            "http://$host:$port/alfresco/service/api/login",
            $h,
            '{"username" : "' . $username . '","password" : "' . $password . '"}'
        );
    my $res = $ua->request($GetReq);
    if ($res->is_success)
    {
        my $hashRef = JSON::decode_json ($res->content);
        $self->{_ticket} = $hashRef->{"data"}->{"ticket"};
        return 1;
    }
    else
    {
        $self->{_errorCode} = $res->{_rc};
        $self->{_errorMsg} = $res->{_msg};
        return 0;
    }
}


#—————————————————————————
sub logout ()
{
    my ($self) = @_;

    my $host = $self->{_host};
    my $port = $self->{_port};
    my $ticket = $self->{_ticket};
    my $ua = LWP::UserAgent->new;
    my $h = HTTP::Headers->new;
    $h->header ('Content-Type' => 'application/json', Accept=>'application/json');
    my $req = HTTP::Request->new
        (
            'DELETE',
            "http://$host:$port/alfresco/service/api/login/ticket/$ticket?alf_ticket=$ticket&format=json",
            $h
        );
    my $res = $ua->request($req);
    if ($res->is_success)
    {
        my $hashRef = JSON::decode_json ($res->content);
        return ($hashRef->{"status"}->{"code"} == 200);
    }
    else
    {
        $self->{_errorCode} = $res->{_rc};
        $self->{_errorMsg} = $res->{_msg};
        return 0;
    }
}

#—————————————————————————
sub errorCode ()
{
    my ($self) = @_;
    return ($self->{_errorCode});
}

#—————————————————————————
sub errorMessage ()
{
    my ($self) = @_;
    return ($self->{_errorMsg});
}

#—————————————————————————
sub dumpPersonInfos ()
{
    my ($self, $personsInfosRef, $level) = @_;
   
    $level = defined ($level) ? $level : 0;
    foreach my $k (keys %{$personsInfosRef})
    {
        my $value = defined ($personsInfosRef->{$k}) ? $personsInfosRef->{$k} : '';
        my $i = 0;
        while ($i < $level)
        {
            print "\t";
            $i += 1;
        }
        print "$k : $value\n";
    }
}

#—————————————————————————
sub getAllPersons ()
{
    my ($self, $personsInfosRef) = @_;
    my $host = $self->{_host};
    my $port = $self->{_port};
    my $ticket = $self->{_ticket};
    my $ua = LWP::UserAgent->new;
    my $h = HTTP::Headers->new;
    $h->header ('Content-Type' => 'application/json', Accept=>'application/json');
    my $req = HTTP::Request->new
        (
            'GET',
            "http://$host:$port/alfresco/service/api/groups/$shortname/children?authorityType=GROUP&alf_ticket=$t...",
            $h
        );
    my $res = $ua->request($req);
    if ($res->is_success)
    {
        return 1;
    }
    else
    {
        $self->{_errorCode} = $res->{_rc};
        $self->{_errorMsg} = $res->{_msg};
        return 0;
    }
}


#—————————————————————————
sub searchPersons ()
{
    my ($self, $filter, $personsInfosRef) = @_;

    my $host = $self->{_host};
    my $port = $self->{_port};
    my $ticket = $self->{_ticket};
    my $ua = LWP::UserAgent->new;
    my $h = HTTP::Headers->new;
    $h->header ('Content-Type' => 'application/json', Accept=>'application/json');
    my $req = HTTP::Request->new
        (
            'GET',
            "http://$host:$port/alfresco/service/api/groups/$shortname/children?authorityType=GROUP&alf_ticket=$t...",
            $h
        );
    my $res = $ua->request($req);
    if ($res->is_success)
    {
        my $hashRef = JSON::decode_json ($res->content);
        my $arrayRef = $hashRef->{"people"};
        foreach my $hRef (@{$arrayRef})
        {
            my %memberInfos;
            foreach my $k (keys %{$hRef})
            {
                $memberInfos {$k} = $hRef->{$k}
            }
            push (@{$personsInfosRef}, \%memberInfos);
        }
        return 1;
    }
    else
    {
        $self->{_errorCode} = $res->{_rc};
        $self->{_errorMsg} = $res->{_msg};
        return 0;
    }
}


#—————————————————————————
sub createPerson ()
{
    my ($self, $personInfosRef) = @_;

    my $host = $self->{_host};
    my $port = $self->{_port};
    my $ticket = $self->{_ticket};
    my $content = JSON::encode_json ($personInfosRef);
    my $ua = LWP::UserAgent->new;
    my $h = HTTP::Headers->new;
    $h->header ('Content-Type' => 'application/json', Accept=>'application/json');
    my $req = HTTP::Request->new
        (
            'POST',
            "http://$host:$port/alfresco/service/api/people?alf_ticket=$ticket",
            $h,
            $content
        );
     my $res = $ua->request($req);
    if ($res->is_success)
    {
        return 1;
    }
    else
    {
        $self->{_errorCode} = $res->{_rc};
        $self->{_errorMsg} = $res->{_msg};
        return 0;
    }
}

#—————————————————————————
sub deletePerson ()
{
    my ($self, $userName) = @_;

    my $host = $self->{_host};
    my $port = $self->{_port};
    my $ticket = $self->{_ticket};
    my $ua = LWP::UserAgent->new;
    my $h = HTTP::Headers->new;
    $h->header ('Content-Type' => 'application/json', Accept=>'application/json');
    my $GetReq = HTTP::Request->new
        (
            'DELETE',
            "http://$host:$port/alfresco/service/api/people/$userName?alf_ticket=$ticket",
            $h
        );
     my $res = $ua->request($GetReq);
    if ($res->is_success)
    {
        return 1;
    }
    else
    {
        $self->{_errorCode} = $res->{_rc};
        $self->{_errorMsg} = $res->{_msg};
        return 0;
    }
}

#—————————————————————————
sub getPersonInfos ()
{
    my ($self, $accountname, $personInfosRef) = @_;

    my $host = $self->{_host};
    my $port = $self->{_port};
    my $ticket = $self->{_ticket};
    my $ua = LWP::UserAgent->new;
    my $h = HTTP::Headers->new;
    $h->header ('Content-Type' => 'application/json', Accept=>'application/json');
    my $req = HTTP::Request->new
        (
            'GET',
            "http://$host:$port/alfresco/service/api/groups/$shortname/children?authorityType=GROUP&alf_ticket=$t...",
            $h
        );
    my $res = $ua->request($req);
    if ($res->is_success)
    {
        %{$personInfosRef} = %{JSON::decode_json ($res->content)};
        return 1;
    }
    else
    {
        $self->{_errorCode} = $res->{_rc};
        $self->{_errorMsg} = $res->{_msg};
        return 0;
    }
}


#—————————————————————————
sub setPersonInfos ()
{
    my ($self, $accountname, $personInfosRef) = @_;

    my $host = $self->{_host};
    my $port = $self->{_port};
    my $ticket = $self->{_ticket};
    my $content = JSON::encode_json ($personInfosRef);
    my $ua = LWP::UserAgent->new;
    my $h = HTTP::Headers->new;
    $h->header ('Content-Type' => 'application/json', Accept=>'application/json');
    my $req = HTTP::Request->new
        (
            'PUT',
            "http://$host:$port/alfresco/service/api/people/$accountname?alf_ticket=$ticket",
            $h,
            $content
        );
     my $res = $ua->request($req);
    if ($res->is_success)
    {
        return 1;
    }
    else
    {
        $self->{_errorCode} = $res->{_rc};
        $self->{_errorMsg} = $res->{_msg};
        return 0;
    }
}


#—————————————————————————
sub dumpGroupInfos ()
{
    my ($self, $groupInfosRef, $level) = @_;
   
    $level = defined ($level) ? $level : 0;
    foreach my $k (keys %{$groupInfosRef})
    {
        my $value = defined ($groupInfosRef->{$k}) ? $groupInfosRef->{$k} : '';
        my $i = 0;
        while ($i < $level)
        {
            print "\t";
            $i += 1;
        }
        print "$k : $value\n";
    }
}

#—————————————————————————
sub createGroup ()
{
    my ($self, $groupInfosRef) = @_;

    my $host = $self->{_host};
    my $port = $self->{_port};
    my $ticket = $self->{_ticket};
    my $shortName = $groupInfosRef->{"shortName"};
    my $content = JSON::encode_json ($groupInfosRef);
    my $ua = LWP::UserAgent->new;
    my $h = HTTP::Headers->new;
    $h->header ('Content-Type' => 'application/json', Accept=>'application/json');
    my $req = HTTP::Request->new
        (
            'POST',
            "http://$host:$port/alfresco/service/api/rootgroups/$shortName?alf_ticket=$ticket",
            $h,
            $content
        );

     my $res = $ua->request($req);
    if ($res->is_success)
    {
        return 1;
    }
    else
    {
        $self->{_errorCode} = $res->{_rc};
        $self->{_errorMsg} = $res->{_msg};
        return 0;
    }
}

#—————————————————————————
sub deleteGroup ()
{
    my ($self, $shortName) = @_;

    my $host = $self->{_host};
    my $port = $self->{_port};
    my $ticket = $self->{_ticket};
    my $ua = LWP::UserAgent->new;
    my $h = HTTP::Headers->new;
    $h->header ('Content-Type' => 'application/json', Accept=>'application/json');
    my $req = HTTP::Request->new
        (
            'DELETE',
            "http://$host:$port/alfresco/service/api/groups/$shortName?alf_ticket=$ticket",
            $h
        );

     my $res = $ua->request($req);
    if ($res->is_success)
    {
        return 1;
    }
    else
    {
        $self->{_errorCode} = $res->{_rc};
        $self->{_errorMsg} = $res->{_msg};
        return 0;
    }
}

#—————————————————————————
sub getAllRootGroups ()
{
    my ($self, $groupInfosRef) = @_;

    my $host = $self->{_host};
    my $port = $self->{_port};
    my $ticket = $self->{_ticket};
    my $ua = LWP::UserAgent->new;
    my $h = HTTP::Headers->new;
    $h->header ('Content-Type' => 'application/json', Accept=>'application/json');
    my $req = HTTP::Request->new
        (
            'GET',
            "http://$host:$port/alfresco/service/api/rootgroups?alf_ticket=$ticket",
            $h
        );
     my $res = $ua->request($req);
    if ($res->is_success)
    {
        my $hashRef = JSON::decode_json ($res->content);
        my $arrayRef = $hashRef->{"data"};
        foreach my $hRef (@{$arrayRef})
        {
            my %memberInfos;
            foreach my $k (keys %{$hRef})
            {
                $memberInfos {$k} = $hRef->{$k}
            }
            push (@{$groupInfosRef}, \%memberInfos);
        }
        return 1;
    }
    else
    {
        $self->{_errorCode} = $res->{_rc};
        $self->{_errorMsg} = $res->{_msg};
        return 0;
    }
}

#—————————————————————————
sub getAllGroups ()
{
    my ($self, $groupInfosRef) = @_;

    my $host = $self->{_host};
    my $port = $self->{_port};
    my $ticket = $self->{_ticket};
    my $ua = LWP::UserAgent->new;
    my $h = HTTP::Headers->new;
    $h->header ('Content-Type' => 'application/json', Accept=>'application/json');
    my $req = HTTP::Request->new
        (
            'GET',
            "http://$host:$port/alfresco/service/api/groups?shortNameFilter=*&alf_ticket=$ticket",
            $h
        );
     my $res = $ua->request($req);
    if ($res->is_success)
    {
        my $hashRef = JSON::decode_json ($res->content);
        my $arrayRef = $hashRef->{"data"};
        foreach my $hRef (@{$arrayRef})
        {
            my %memberInfos;
            foreach my $k (keys %{$hRef})
            {
                $memberInfos {$k} = $hRef->{$k}
            }
            push (@{$groupInfosRef}, \%memberInfos);
        }
        return 1;
    }
    else
    {
        $self->{_errorCode} = $res->{_rc};
        $self->{_errorMsg} = $res->{_msg};
        return 0;
    }
}

#—————————————————————————
sub searchGroups ()
{
    my ($self, $filter, $groupInfosRef) = @_;

    print "getAllGroups :\n";
    my $host = $self->{_host};
    my $port = $self->{_port};
    my $ticket = $self->{_ticket};
    my $ua = LWP::UserAgent->new;
    my $h = HTTP::Headers->new;
    $h->header ('Content-Type' => 'application/json', Accept=>'application/json');
    my $req = HTTP::Request->new
        (
            'GET',
            "http://$host:$port/alfresco/service/api/groups?shortNameFilter=$filter&alf_ticket=$ticket",
            $h
        );
     my $res = $ua->request($req);
    if ($res->is_success)
    {
        my $hashRef = JSON::decode_json ($res->content);
        my $arrayRef = $hashRef->{"data"};
        foreach my $hRef (@{$arrayRef})
        {
            my %memberInfos;
            foreach my $k (keys %{$hRef})
            {
                $memberInfos {$k} = $hRef->{$k}
            }
            push (@{$groupInfosRef}, \%memberInfos);
        }
        return 1;
    }
    else
    {
        $self->{_errorCode} = $res->{_rc};
        $self->{_errorMsg} = $res->{_msg};
        return 0;
    }
}

#—————————————————————————
sub getGroupInfos ()
{
    my ($self, $shortname, $groupInfosRef) = @_;

    my $host = $self->{_host};
    my $port = $self->{_port};
    my $ticket = $self->{_ticket};
    my $ua = LWP::UserAgent->new;
    my $h = HTTP::Headers->new;
    $h->header ('Content-Type' => 'application/json', Accept=>'application/json');
    my $req = HTTP::Request->new
        (
            'GET',
            "http://$host:$port/alfresco/service/api/groups/$shortname?alf_ticket=$ticket",
            $h
        );
    my $res = $ua->request($req);
    if ($res->is_success)
    {
        my $hashRef = JSON::decode_json ($res->content);
        foreach my $k (keys %{$hashRef->{"data"}})
        {
            $groupInfosRef->{$k} = $hashRef->{"data"}->{$k};
        }
        return 1;
    }
    else
    {
        $self->{_errorCode} = $res->{_rc};
        $self->{_errorMsg} = $res->{_msg};
        return 0;
    }
}


#—————————————————————————
sub getGroupDirectMembers ()
{
    my ($self, $shortname, $groupMembersRef) = @_;

    my $host = $self->{_host};
    my $port = $self->{_port};
    my $ticket = $self->{_ticket};
    my $ua = LWP::UserAgent->new;
    my $h = HTTP::Headers->new;
    $h->header ('Content-Type' => 'application/json', Accept=>'application/json');
    my $req = HTTP::Request->new
        (
            'GET',
            "http://$host:$port/alfresco/service/api/groups/$shortname/children?alf_ticket=$ticket",
            $h
        );
    my $res = $ua->request($req);
    if ($res->is_success)
    {
        my $hashRef = JSON::decode_json ($res->content);
        my $arrayRef = $hashRef->{"data"};
        foreach my $hRef (@{$arrayRef})
        {
            my %memberInfos;
            foreach my $k (keys %{$hRef})
            {
                $memberInfos {$k} = $hRef->{$k}
            }
            push (@{$groupMembersRef}, \%memberInfos);
        }
        return 1;
    }
    else
    {
        $self->{_errorCode} = $res->{_rc};
        $self->{_errorMsg} = $res->{_msg};
        return 0;
    }
}


#—————————————————————————
sub getGroupDirectPersons ()
{
    my ($self, $shortname, $groupMembersRef) = @_;

    my $host = $self->{_host};
    my $port = $self->{_port};
    my $ticket = $self->{_ticket};
    my $ua = LWP::UserAgent->new;
    my $h = HTTP::Headers->new;
    $h->header ('Content-Type' => 'application/json', Accept=>'application/json');
    my $req = HTTP::Request->new
        (
            'GET',
            "http://$host:$port/alfresco/service/api/groups/$shortname/children?authorityType=USER&alf_ticket=$ti...",
            $h
        );
    my $res = $ua->request($req);
    if ($res->is_success)
    {
        my $hashRef = JSON::decode_json ($res->content);
        my $arrayRef = $hashRef->{"data"};
        foreach my $hRef (@{$arrayRef})
        {
            my %memberInfos;
            foreach my $k (keys %{$hRef})
            {
                $memberInfos {$k} = $hRef->{$k}
            }
            push (@{$groupMembersRef}, \%memberInfos);
        }
        return 1;
    }
    else
    {
        $self->{_errorCode} = $res->{_rc};
        $self->{_errorMsg} = $res->{_msg};
        return 0;
    }
}

#—————————————————————————
sub getGroupDirectSubGroups ()
{
    my ($self, $shortname, $groupMembersRef) = @_;

    my $host = $self->{_host};
    my $port = $self->{_port};
    my $ticket = $self->{_ticket};
    my $ua = LWP::UserAgent->new;
    my $h = HTTP::Headers->new;
    $h->header ('Content-Type' => 'application/json', Accept=>'application/json');
    my $req = HTTP::Request->new
        (
            'GET',
            "http://$host:$port/alfresco/service/api/groups/$shortname/children?authorityType=GROUP&alf_ticket=$t...",
            $h
        );
    my $res = $ua->request($req);
    if ($res->is_success)
    {
        my $hashRef = JSON::decode_json ($res->content);
        my $arrayRef = $hashRef->{"data"};
        foreach my $hRef (@{$arrayRef})
        {
            my %memberInfos;
            foreach my $k (keys %{$hRef})
            {
                $memberInfos {$k} = $hRef->{$k}
            }
            push (@{$groupMembersRef}, \%memberInfos);
        }
        return 1;
    }
    else
    {
        $self->{_errorCode} = $res->{_rc};
        $self->{_errorMsg} = $res->{_msg};
        return 0;
    }
}


#—————————————————————————
sub addPersonToGroup ()
{
    my ($self, $userName, $shortName) = @_;

    my $host = $self->{_host};
    my $port = $self->{_port};
    my $ticket = $self->{_ticket};
    my $ua = LWP::UserAgent->new;
    my $h = HTTP::Headers->new;
    $h->header ('Content-Type' => 'application/json', Accept=>'application/json');
    my $req = HTTP::Request->new
        (
            'POST',
            "http://$host:$port/alfresco/service/api/groups/$shortName/children/$userName?alf_ticket=$ticket",
            $h
        );

    my $res = $ua->request($req);
    if ($res->is_success)
    {
        return 1;
    }
    else
    {
        $self->{_errorCode} = $res->{_rc};
        $self->{_errorMsg} = $res->{_msg};
        return 0;
    }
}


#—————————————————————————
sub removePersonFromGroup ()
{
    my ($self, $userName, $shortName) = @_;

    my $host = $self->{_host};
    my $port = $self->{_port};
    my $ticket = $self->{_ticket};
    my $ua = LWP::UserAgent->new;
    my $h = HTTP::Headers->new;
    $h->header ('Content-Type' => 'application/json', Accept=>'application/json');
    my $req = HTTP::Request->new
        (
            'DELETE',
            "http://$host:$port/alfresco/service/api/groups/$shortName/children/$userName?alf_ticket=$ticket",
            $h
        );

    my $res = $ua->request($req);
    if ($res->is_success)
    {
        return 1;
    }
    else
    {
        $self->{_errorCode} = $res->{_rc};
        $self->{_errorMsg} = $res->{_msg};
        return 0;
    }
}

#—————————————————————————
sub addSubGroupToGroup ()
{
    my ($self, $subGroupName, $groupName) = @_;

    my $host = $self->{_host};
    my $port = $self->{_port};
    my $ticket = $self->{_ticket};
    my $ua = LWP::UserAgent->new;
    my $h = HTTP::Headers->new;
    $h->header ('Content-Type' => 'application/json', Accept=>'application/json');
    my $req = HTTP::Request->new
        (
            'POST',
            "http://$host:$port/alfresco/service/api/groups/$groupName/children/GROUP_$subGroupName?alf_ticket=$t...",
            $h
        );

    my $res = $ua->request ($req);
    if ($res->is_success)
    {
        return 1;
    }
    else
    {
        $self->{_errorCode} = $res->{_rc};
        $self->{_errorMsg} = $res->{_msg};
        return 0;
    }
}

#—————————————————————————
sub removeSubGroupFromGroup ()
{
    my ($self, $subGroupName, $groupName) = @_;

    my $host = $self->{_host};
    my $port = $self->{_port};
    my $ticket = $self->{_ticket};
    my $ua = LWP::UserAgent->new;
    my $h = HTTP::Headers->new;
    $h->header ('Content-Type' => 'application/json', Accept=>'application/json');
    my $req = HTTP::Request->new
        (
            'DELETE',
            "http://$host:$port/alfresco/service/api/groups/$groupName/children/GROUP_$subGroupName?alf_ticket=$t...",
            $h
        );

    my $res = $ua->request($req);
    if ($res->is_success)
    {
        return 1;
    }
    else
    {
        $self->{_errorCode} = $res->{_rc};
        $self->{_errorMsg} = $res->{_msg};
        return 0;
    }
}

1;

And use It like that :
use warnings;
use strict;

use Alfresco;

my $host = 'localhost';
my $port = 8080;

print "host : $host\n";

print "admin: ";
my $admin = <STDIN>;
chomp ($admin);

print "password: ";
my $password = <STDIN>;
chomp ($password);

my $alfresco = new Alfresco ($host, $port);
if ($alfresco->login ($admin, $password))
{
   print "$admin is logged on…\n";
   print "Person creation :\n";
   print "userName : ";
   my $userName = <STDIN>;
   chomp ($userName);
   print "firstName : ";
   my $firstName = <STDIN>;
   chomp ($firstName);
   print "lastName : ";
   my $lastName = <STDIN>;
   chomp ($lastName);
   print "email : ";
   my $email = <STDIN>;
   chomp ($email);
   
   my %personInfos;
   $personInfos {"userName"} = $userName;
   $personInfos {"password"} = $userName;
   $personInfos {"firstName"} = $firstName;
   $personInfos {"lastName"} = $lastName;
   $personInfos {"email"} = $email;

   if ($alfresco->createPerson (\%personInfos))
   {
      print "$userName created !\n";
      my %infos;
      if ($alfresco->getPersonInfos ($userName, \%infos))
      {
         $alfresco->dumpPersonInfos (\%infos, 1);
      }
      else
      {
         print "getPersonInfos ($userName, …) failed !\n";
      }
   }
   else
   {
      print "Can't create $userName\n";
   }
   if ($alfresco->logout ())
   {
      print "$admin is now logged out\n";
   }
   else
   {
      print "unable to logged out $admin…\n";
   }
}
else
{
   print "$admin can't log in $host:$port\n";
}

I hope It helps

Bruno