Andrea Girardi - It's my blog!

Tag: Alfresco

Debug content model in Alfresco

When you need to customize Alfresco content model, not always everything works fine so, it’s necessary to find a way to check if your model is correct or not. It’s possible to use the built-in Get Class Definitions webscript to debug. Basically, you can use this webscript to see if an expected content type exists on Alfresco or not. You can also use this webscript to see if an expected content type exists on Alfresco or not. All you have to do is to call the webscript with your class name which in this case myroot:mycontent for me.

http://localhost:8086/alfresco/service/api/classes/myroot_mycontent

Or you can call the same webscript without a class name, in this case webscript will dump every content type that exists on Alfresco.

The response will be something like that:

 
   {
      "name": "labtest:Labtest_content",
      "isAspect": false,
      "isContainer": false,
      "title": "Labtest content model",
      "description": "",
      "parent":
      {
         "name": "cm:content",
         "title": "content",
         "url": "/api/classes/cm_content"
      },
      "defaultAspects":
      {
         "sys:referenceable":
         {
            "name": "sys:referenceable",
            "title": "Referenceable",
            "url": "/api/classes/labtest_Labtest_content/property/sys_referenceable"
         },
         "sys:localized":
         {
            "name": "sys:localized",
            "title": "Translation",
            "url": "/api/classes/labtest_Labtest_content/property/sys_localized"
         },
         "cm:auditable":
         {
            "name": "cm:auditable",
            "title": "Auditable",
            "url": "/api/classes/labtest_Labtest_content/property/cm_auditable"
         }
      },
      "properties":
      {
         "cm:name":
         {
            "name": "cm:name",
            "title": "Name",
            "description": "Name",
            "dataType": "d:text",
            "defaultValue": null,
            "multiValued": false,
            "mandatory": true,
            "enforced": true,
            "protected": false,
            "indexed": true,
            "url": "/api/classes/labtest_Labtest_content/property/cm_name"
         },
         "labtest:Labtest_result_name":
         {
            "name": "labtest:Labtest_result_name",
            "title": "Labtest result name [java uses to get this content]",
            "description": "",
            "dataType": "d:text",
            "defaultValue": null,
            "multiValued": false,
            "mandatory": false,
            "enforced": false,
            "protected": false,
            "indexed": true,
            "url": "/api/classes/labtest_Labtest_content/property/labtest_Labtest_result_name"
         },
         "cm:content":
         {
            "name": "cm:content",
            "title": "Content",
            "description": "Content",
            "dataType": "d:content",
            "defaultValue": null,
            "multiValued": false,
            "mandatory": false,
            "enforced": false,
            "protected": false,
            "indexed": true,
            "url": "/api/classes/labtest_Labtest_content/property/cm_content"
         }
      },
      "associations":
      {
 
         "labtest:labtest_static_components":
         {
            "name": "labtest:labtest_static_components",
            "title": "Labtest static components",
            "url": "/api/classes/labtest_Labtest_content/association/labtest_labtest_static_components",
            "source":
            {
               "class": "labtest:Labtest_content",
 
               "mandatory": true,
               "many": true
            },
            "target":
            {
               "class": "labtest:Labtest_static_component",
 
               "mandatory": false,
               "many": true
            }
         }
         ,
         "labtest:labtest_dynamic_components":
         {
            "name": "labtest:labtest_dynamic_components",
            "title": "Labtest dynamic components",
            "url": "/api/classes/labtest_Labtest_content/association/labtest_labtest_dynamic_components",
            "source":
            {
               "class": "labtest:Labtest_content",
 
               "mandatory": true,
               "many": true
            },
            "target":
            {
               "class": "labtest:Labtest_dynamic_component",
 
               "mandatory": false,
               "many": true
            }
         }
      },
      "childassociations":
      {
 
 
      },
      "url": "/api/classes/labtest_Labtest_content"
   }

Resolving java.lang.OutOfMemoryError: PermGen

Today our Alfresco doesn’t start due to this error:

java.lang.OutOfMemoryError: PermGen

The PermGen (permanent generation) holds data needed by the virtual machine to describe objects that do not have an equivalence at the Java language level like objects describing classes and methodse. So often large, complex apps will need lots of PermGen space. Similarly if you are doing frequent war/ear/jar deployments to running servers like Tomcat or JBoss you may need to issue a server restart after a few deploys or increase your PermGen space.

To increase the PermGen space use something like:

-XX:MaxPermSize=128m

The default is 64MB.

Note that Xmx is separate from the PermGen space, so increasing Xmx will not help with the PermGen errors (PermGen memory is in addition to the Xmx memory)

Java has other settings that could help control how much memory it uses:

-Xmx sets the maximum memory heap size
-Xms sets the minimum memory heap size.

Show post categories using Webscript

To show all categories of a post, check if the cm:categories child association exists and, if yes, list all childs into the ftl file:

<#if node.properties["cm:categories"]?exists>
	<categories>
		<#list node.properties["cm:categories"] as prop>${prop.name}</#list>
	</categories>
</#if>

Download Alfresco content from Java using Spring

To download content stored on Alfresco repository using Java, this is one possible way:

String url = "http://localhost:18080/alfresco/d/a/workspace/SpacesStore/" + attach.getNode_ref() + "/" + attach.getAttach_filename() + "?ticket=" + ticket;
return new ModelAndView("redirect:" + url);

Where getNode_ref() is a method that returns the node reference ID and getAttach_filename() returns the file name. In that case the authentication ticket is attached to the request because the Alfresco guest user is disable.

To view the content instead of dowload it, change the url into:

http://localhost:18080/alfresco/d/d/workspace/SpacesStore/

Query Alfresco Web script using REST

With Spring 3 querying a REST-based service it’s easy. For first, you need to authenticate on Alfresco repository using an Alfresco Ticket instead of an explicit user name and password. A ticket represents a pre-authenticated user who has already performed the login process. To log in, the url is:

http://localhost:8081/alfresco/service/api/login?u=admin&amp;pw=admin

Assuming the userid and password are correct, Alfresco will respond back with this simple XML:

<!--?xml version="1.0" encoding="UTF-8"?-->
TICKET_18d49dbd5de400c3fa1254b46e46ac51fbd0934e

Using Spring and Java you should write something like that:

RestTemplate restTemplate = new RestTemplate();
Map params = new HashMap();
params.put("user", login);
params.put("password", password);
String url = "http://localhost:8081/alfresco/service/api/login?u={user}&amp;pw={password}";
Source result = restTemplate.getForObject(url, Source.class, params);
XPathOperations xpath = new Jaxp13XPathTemplate();			
this.authenticationTicket = xpath.evaluateAsString("//ticket", result);

The RestTemplate was introduced in Spring 3 to give REST access the same support as JDBC, passing a Map of keywords and values. It serves as a wrapper to hide all the details in accessing REST resources, including opening and closing connection objects and converting responses to Java objects. Source class is the return type.

Once authenticated, we are ready to call Web script to query Alfresco repository:

http://localhost:8081/alfresco/service/kipcast/search/brand.xml?q={keyword}&alf_ticket={ticket}

This web script returns an XML like that:

<brands>
	<brand>
		<nodeRef>a8a4c38d-67fb-475b-84cb-9cf912dfac58</nodeRef>
		<name>Name1</name>
		<supplierName>
			Company1
		</supplierName>					
		<relatedCommonName>
			RelatedCommonName1
		</relatedCommonName>
	</brand>
</brands>

The above response needs some configuration to marshall objects to XML. All we need to do is define it in our application context and, for that to work fine, you need to tell the marshaller which annotated classes you have:

<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
    <property name="messageConverters">
        <list>
            <bean id="messageConverter" class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
                <property name="marshaller" ref="marshaller" />
                <property name="unmarshaller" ref="marshaller" />
            </bean>
        </list>
    </property>        
</bean>
 
 
<bean name="marshaller" class="org.springframework.oxm.xstream.XStreamMarshaller">
    <property name="autodetectAnnotations" value="true"/>
    <property name="annotatedClasses">
        <array>
            <value>com.kipcast.dataModel.drugs.bean.Brands</value>
            <value>com.kipcast.dataModel.drugs.bean.Brand</value>
        </array>
    </property>
</bean>

At this point we can simply instantiate a RestTemplate object by calling the getBean method on the application context. This is the Java code to do that:

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("alfresco-context.xml");
RestTemplate restTemplate = applicationContext.getBean("restTemplate", RestTemplate.class);	
 
Map<String, String> params = new HashMap<String, String>();
params.put("ticket", this.authenticationTicket);	
params.put("keyword", key);	
String url = "http://localhost:8081/alfresco/service/kipcast/search/brand.xml?q={keyword}&alf_ticket={ticket}";
Brands brandList = (Brands) restTemplate.getForObject(url, Brands.class, params);

Last thing is modify the two beans Brands and Brand putting the proper annotations to both classes:

@XStreamAlias("brands")
public class Brands {
 
	@XStreamImplicit
	List<Brand> brandList = new ArrayList<Brand>(); 
 
    public List<Brand> getBrands() {
        return brandList;
    }
 
	public void setBrands(List<Brand> brandList) {
	    this.brandList = brandList;
	}
 
	public void addBrands(Brand brand) {
	    this.brandList.add(brand);
	}
 
}
 
@XStreamAlias("brand")
public class Brand {
 
	private String nodeRef;
	private String name;
	private String relatedCommonName;
	private String supplierName;
 
        // Getter and setter methods
}

For more details please take a look to thekspace.com, tedwise.com and springsource.com.

Copyright © 2017 Andrea Girardi – It's my blog!

Theme by Anders NorenUp ↑