Forums de discussion

How to populate a Journal Article with values programmatically

thumbnail
Charalampos Chrysikopoulos, modifié il y a 12 années.

How to populate a Journal Article with values programmatically

Junior Member Publications: 79 Date d'inscription: 09/12/11 Publications récentes
Hello,

my problem is to create a new journal article with a given structure in a port let. The re is no problem if I want to crete an article without a structure. In this case I use the method
JournalArticleLocalServiceUtil.addArticle

and through the parameters I can populate the content.

But what happens if we have a complicated structure with repeatable items? How can we pass the values of the article content in the journal article?

Looking at th source code of the portal, I found the JournalUtil class, that builds an XML for the content, that looks al lot like the structure XML, but it has also elements of type content-value for the values of each node and an attribute instance-id that looks like a generated id.

For example if I have the structure

<root>
	<dynamic-element name="video" type="text" index-type="" repeatable="true">
		<dynamic-element name="videoDescription" type="text" index-type="text" repeatable="false" />
	</dynamic-element>
	<dynamic-element name="image" type="document_library" index-type="" repeatable="true">
		<dynamic-element name="imageAltText" type="text" index-type="text" repeatable="false" />
	</dynamic-element>
	<dynamic-element name="content" type="text_area" index-type="text" repeatable="false" />
	<dynamic-element name="articleId" type="text" index-type="" repeatable="false" />
</root>


and I create a journal article for with this structure in control panel, the XML looks like

<root available-locales="en_US" default-locale="en_US">
	<dynamic-element instance-id="Tc2g1u4f" name="video" type="text" index-type="">
		<dynamic-element instance-id="d9iKBUeZ" name="videoDescription" type="text" index-type="text">
			<dynamic-content>fsdafagadfbcvxb</dynamic-content>
		</dynamic-element>
		<dynamic-content>sdfsdafsadfsadfsd</dynamic-content>
	</dynamic-element>
	<dynamic-element instance-id="KnxJI9SL" name="image" type="document_library" index-type="">
		<dynamic-element instance-id="ffU3EVnL" name="imageAltText" type="text" index-type="text">
			<dynamic-content>dsfgdfsgdsfg</dynamic-content>
		</dynamic-element>
		<dynamic-content>/documents/10180/35002/0aea5587248ccccdc96aec80c7764fa7_M.jpg/f6a4be84-8e03-4972-9e69-c048405e5f54</dynamic-content>
	</dynamic-element>
	<dynamic-element instance-id="DcSmo4bP" name="content" type="text_area" index-type="text">
		<dynamic-content>&lt;p&gt; gsdfgdfsgsdfg&lt;/p&gt; &lt;p&gt; sdfgsdfg&lt;/p&gt; &lt;p&gt; &amp;nbsp;&lt;/p&gt; &lt;p&gt; &amp;nbsp;&lt;/p&gt; &lt;p&gt; dsfg&lt;/p&gt; &lt;p&gt; dsfgd&lt;span style="background-color:#ff8c00;"&gt;sfgdsfgdfsgsd&lt;/span&gt;fg&lt;/p&gt;</dynamic-content>
	</dynamic-element>
	<dynamic-element instance-id="nqW29dZs" name="articleId" type="text" index-type="">
		<dynamic-content>4234</dynamic-content>
	</dynamic-element>
</root>


I tried to construct this XML, but the addArticle method gave me an exception

com.liferay.portlet.journal.ArticleContentException
	at com.liferay.portlet.journal.service.impl.JournalArticleLocalServiceImpl.validateContent(JournalArticleLocalServiceImpl.java:3416)
	at com.liferay.portlet.journal.service.impl.JournalArticleLocalServiceImpl.validate(JournalArticleLocalServiceImpl.java:3303)


So, my question is, is there a way to construct this XML with the generated values through the Liferay API ? Or do I have to construct this by myself? I couldn't find any wiki documents or other help y googling around...

Thanks in advance.
thumbnail
Jan Eerdekens, modifié il y a 11 années.

RE: How to populate a Journal Article with values programmatically

New Member Publications: 15 Date d'inscription: 20/01/11 Publications récentes
I'm currently trying the same thing and I've been able to add an article based on a custom structure and template using this XML. There doesn't seem to be (as far as I can see) a utility class that helps with creating this XML. The best way to figure out the correct parameters and the XML content as well is to just open an debug session and put a breakpoint in the EditArticleAction class and go from there.

If you're able to provide some additional information about your exception I might be able to help you determine the exact problem in your case, but the current portion of the stacktrace doesn't provide enough information.
Edouard Perr, modifié il y a 11 années.

RE: How to populate a Journal Article with values programmatically

Junior Member Publications: 30 Date d'inscription: 20/08/12 Publications récentes
Hi there!

I am currently working on it too and I am wondering the same question.
Acutally, I manage to create (partially, I will explain why...) a new article in Liferay using this method. Here is the call :
(sorry for french comments...)


try {
			Document doc = SAXReaderUtil.read(loadXmlContentTemplate());
              
                        // Remplissage des champs du Document à l'aide d'une hashMap (data) contenant 
                        // les attributs "name" du "dynamic-element" en KEY et les valeurs associés.
			for (String key : data.keySet()) {
				Node node = doc.selectSingleNode("/root/dynamic-element[@name='" + key + "']/dynamic-content");
				node.setText("" + data.get(key) + "");
			}

			// Génération de la chaine Content à envoyer à Liferay --&gt; lorsque traité par asXML(), les chevrons du CDATA sont transformé en code Html
			String createdContentXml = StringEscapeUtils.unescapeXml(doc.asXML());

			// titleMap reprend les différents language, obligatoire
			Map<locale, string> titleMap = new HashMap<locale, string>();
			titleMap.put(Locale.FRANCE, 
					data.get("id") +
					" - " +
					data.get("titre");

                        // Pour les champs INT obligatoires (displayDate)
			GregorianCalendar date = (GregorianCalendar) GregorianCalendar.getInstance(TimeZone.getTimeZone("Europe/Paris"), Locale.FRANCE);

			// Le serviceContext est obligatoire, ces différents champs sont optionnels SAUF groupId
			ServiceContext serviceContext = new ServiceContext();
			serviceContext.setScopeGroupId(Long.parseLong(PortletProps.get("groupId")));

			JournalArticle addedTrip = JournalArticleLocalServiceUtil.addArticle(
					Long.parseLong(PortletProps.get("userId")), 
					Long.parseLong(PortletProps.get("groupId")), 
					0L,					//classNameId
					0L,					//classPK
					"", 				// articleId -&gt; ne peut pas être null
					true,				//autoArticleId
					1D,					//version
					titleMap, 			// hashmap titre défini au dessus
					null, 				//descriptionMap
					createdContentXml,	// content en xml généré plus haut
					PortletProps.get("articleType"),		// type, ne peut pas être null ou vide
					PortletProps.get("structureId"),	       // structure de l'article, je ne sais pas si peut être null ou vide...
					PortletProps.get("templateId"),           // template de l'article, je ne sais pas si peut être null ou vide...
					null,		// layoutUuid
					date.get(Calendar.MONTH), 		// | 
					date.get(Calendar.DAY_OF_MONTH), 	// | 
					date.get(Calendar.YEAR), 			// | --&gt; displayDate 
					date.get(Calendar.HOUR), 			// |
					date.get(Calendar.MINUTE), 		// |
					0, // |
					0, // |
					0, // |--&gt;  expireDate, peut être null, vide ou 0 si neverExpire = true, sinon Attention aux contraintes!
					0, // |
					0, // |
					true, // neverExpire
					0, // |
					0, // |
					0, // |--&gt; ReviewDate, peut être null, vide ou 0 si neverReview = true, sinon Attention aux contraintes!
					0, // |
					0, // |
					true,		// neverReview
					true,		// indexable
					false, 		// smallImage 
					null, 		// null  |
					null, 		// null  | ==&gt; arguments concernant les images.
					null, 		// null  |
					null, 		// null  |
					serviceContext       //serviceContexte obligatoire, avec au moins scopeGroupId (= groupId de l'article)
					);
		// Exceptions pouvant être levées : 
		// DocumentException / NumerFormatException / PortalException / SystemException
		} catch( Exception e) {
			e.printStackTrace();
		}
</locale,></locale,>


Here is some parts of the xml I use to generate the content String :
I have many other fields but it's exactly the same
<root available-locales="fr_FR" default-locale="fr_FR">
	<dynamic-element name="titre1" type="text" index-type="">
		<dynamic-content></dynamic-content>
	</dynamic-element>
	<dynamic-element name="description-longue" type="text_area" index-type="">
		<dynamic-content></dynamic-content>
	</dynamic-element>
</root>


Whith all these arguments in the addArticle() method, I manage to create my article, and make it appeared in the web content list.
However, I am facing a big issue, maybe a bug of Liferay :

The "text-area" fields remain empty, but "text" fields are well display.
If I click on the action "View" (to view it using the velocity template), the text-area is shown normally whith the right content.
This is the first issue.

The second issue :
As soon as I modified a fields (whatever which one), all my content disapears, all my fields are empty except the mandatory articleTitle (not part of my structure). The article view with the velocity template doesn't work anymore and show me my vm variables ($myField.getData()).
So I suppose my content is lost. I can fill in my fields from the edit page, and work normally with my article.

From here, Where can the problem come from ? Answer: I think, from the attribute instance-id in the XML.
As it is a generated value by Liferay, I didn't put this dynamic-content attribute in my xml used to generate the content String. And in fact, when I download the article (with the download button in the edit view), all my fields in the downloaded xml has a 'null' instance-id.
After editing and saving the desappeared fields, the newly downloaded xml includes now an instance-id, generated.

Now the relevant question is : How to tell Liferay to generate those instance-id from the beginning and avoid this loss of data?

Thnaks for reading. emoticon
Edouard Perr, modifié il y a 11 années.

RE: How to populate a Journal Article with values programmatically

Junior Member Publications: 30 Date d'inscription: 20/08/12 Publications récentes
After lots of tests, I manage to identify the origin of the issue.
In fact, the instance-id is mandatory in the xml String (to put into the content attribute).
If I leave it blank (instance-id="") instead of nothing, it's good my data are persisted and the instance-id is generated.

One trouble remains for text-area dynamic-element, if I leave the instance-id blank, the content in the journal edit page appears as the whole XML file. But if I clic on view article (with my template), the text-area is correctly rendered, and if I download it, the xml is correct, and my rich text is correlty retrieved.

I continue to work on it, although I don't know what I should look for, and it is dificult to find information about it on Liferay/google...
Robert Berg, modifié il y a 11 années.

RE: How to populate a Journal Article with values programmatically

New Member Envoyer: 1 Date d'inscription: 13/06/12 Publications récentes
You should fill the instance-id attribute, don't leave it blank.

public String generateInstanceId() {
	StringBuilder instanceId = new StringBuilder(8);

	String key = PwdGenerator.KEY1 + PwdGenerator.KEY2 + PwdGenerator.KEY3;
		
	for (int i = 0; i &lt; 8; i++) {
		int pos = (int)Math.floor(Math.random() * key.length());

		instanceId.append(key.charAt(pos));
	}
	return instanceId.toString();
}
Gwowen Fu, modifié il y a 11 années.

RE: How to populate a Journal Article with values programmatically

Expert Publications: 315 Date d'inscription: 27/12/10 Publications récentes
Simply use PwdGenerator.getPassword() to generate instance ID.
thumbnail
vamsi nath reddy, modifié il y a 9 années.

RE: How to populate a Journal Article with values programmatically

New Member Publications: 2 Date d'inscription: 19/02/15 Publications récentes
I have same problem. I want to pass values in selection -list and multi selection -list. Can anyone help me emoticon
thumbnail
Himanshu Bhandari, modifié il y a 8 années.

RE: How to populate a Journal Article with values programmatically

Regular Member Publications: 148 Date d'inscription: 09/05/14 Publications récentes
Hi
You have
String[] items  =  ParamUtil.getParameterValues(request, "param");

Thanks.