Creating a Web Content is easy via the UI.
But how to do add a new Web Content programmatically, in Java?
I must migrate data from a legacy system to Liferay 7, so I am writing a Java OSGI bundle to do so. No user interface.
Nicolas.
I had a similar problem to solve in Liferay 6.2, but I believe you can solve yours using the same approach.
We built a "integration interface" (a simple Java Batch project to trigger the whole thing) that comunicates with the legacy system and with a Liferay REST Service (created using Liferay Service Builder).
Liferay provides you a Service API where you can handle some of its resources. To create a Journal Article (Web Content) you must invoke the Class JournalArticleLocalServiceUtil
Here is a sample code to create a Journal Article:
public static JournalArticle addJournalArticle(
long userId, long groupId, String title, String contentEn)
throws Exception {
ServiceContext serviceContext = new ServiceContext();
serviceContext.setAddGroupPermissions(true);
serviceContext.setAddGuestPermissions(true);
serviceContext.setScopeGroupId(groupId);
serviceContext.setWorkflowAction(WorkflowConstants.ACTION_PUBLISH);
Map<Locale, String> titleMap = new HashMap<Locale, String>();
Map<Locale, String> descriptionMap = new HashMap<Locale, String>();
titleMap.put(Locale.US, title);
descriptionMap.put(Locale.US, title);
try {
JournalArticleLocalServiceUtil.deleteArticle(groupId, title, serviceContext);
} catch (Exception ex) {
System.out.println("Ignoring " + ex.getMessage());
}
String xmlContent = "<?xml version='1.0' encoding='UTF-8'?>" +
"<root default-locale=\"en_US\" available-locales=\"en_US\">" +
"<static-content language-id=\"en_US\">" +
"<![CDATA[" + contentEn + "]]>" +
"</static-content>" +
"</root>";
JournalArticle article = JournalArticleLocalServiceUtil.addArticle(
userId, groupId, 0,
0, 0, title, true,
JournalArticleConstants.VERSION_DEFAULT, titleMap,
descriptionMap, xmlContent,
"general", null, null, null,
1, 1, 2014, 0, 0,
0, 0, 0, 0, 0, true,
0, 0, 0, 0, 0, true,
true, false, null, null,
null, null, serviceContext);
return article;
}
But you must to improve it to put the correct user permissions, categories, tags and etc.
In such cases it helps to look at the source code.
Also consider using an Upgrade Process. While your case is not really an update it sounds like a one time operation which you would ideally perform on startup.
Related
Iam adding a file to folder by this way
if(fileExisits(folderId, title))
{
fileEntry=DLFileEntryLocalServiceUtil.getFileEntry(repositoryId, folderId, title);
serviceContext.setWorkflowAction(0);
DLFileEntryLocalServiceUtil.updateFileEntry(userId, fileEntry.getFileEntryId(), sourceFileName, mimeType, title, description, changeLog, true, fileEntry.getFileEntryTypeId(), null, null, is, size, serviceContext);
}
else
{
serviceContext.setWorkflowAction(0);
DLFileEntryLocalServiceUtil.addFileEntry(userId, repositoryId, repositoryId, folderId, sourceFileName, mimeType, title, description, changeLog, 0, null, null, is, size, serviceContext);
}
But even though it is updating or creating a dlfile it is being saved as draft.
Can anyone please help me how to change the status of dlfile programaticaly.
Maybe you should try serviceContext.setWorkflowAction(WorkflowConstants.ACTION_PUBLISH)
I found the solution i was adding user and group to servicecontext now instead iam using new ServiceContext() . By doing so iam able to create as dlfile with approvied status
We create a pdf-download URL in our Liferay Portal 6.1 EE via following
method call:
String fileUrl = DLUtil.getPreviewURL(file, fileVersion, null, StringPool.BLANK, false, true);
Is it possible to remove the generated "number-letter-combination" (bold text) from the link or place it at a certain point in the url ?
documents/10180/1423151/AT0000753173_FAT.pdf/461a1fdf-6e61-4cb3-8c1d-77cb527e3609
Thanks a lot for any hints.
the "number-letter-combination" is the file uuid field and there is no way to move that calling the method DLUtil.getPreviewURL. But you can build the url yourself in this way
StringBundler sb = new StringBundler();
sb.append(PortalUtil.getPathContext());
sb.append("/documents/");
sb.append(fileEntry.getRepositoryId());
sb.append(StringPool.SLASH);
sb.append(fileEntry.getFolderId());
sb.append(StringPool.SLASH);
sb.append(HttpUtil.encodeURL(HtmlUtil.unescape(fileEntry.getTitle())));
fileUrl = sb.toString()
I need to change document types (FileEntryType) for a large list of files in Liferay Document Library, but I have not been able to do so.
After hours of googeling, testing and familiarizing myself with Liferay Github repo, I decided to come here and ask for help.
This is what I have used:
ServiceContext serviceContext = new ServiceContext();
List<DLFileEntry> filesToBeUpdated = DLFileEntryServiceUtil.getFileEntries(
groupId, 0, fileEntryTypeId,
0, 10000, OrderByComparator);
for (DLFileEntry file : filesToBeUpdated) {
System.out.println("Changing file: "+ file.getName());
serviceContext.setAttribute("fileEntryTypeId", fileEntryTypeId);
DLAppServiceUtil.updateFileEntry(file.getFileEntryId(), file.getName(),
file.getMimeType(), null, file.getDescription(),
null, false, null, file.getSize(), serviceContext);
}
The files I used for testing are found correctly. The problem is with updating in the for loop: It throws always PortletException. How can I change the FileEntryType correctly?
You can also accomplish this with DLAppServiceUtil by setting the field in the ServiceContext that you pass in as the last parameter:
sc.setAttribute("fileEntryTypeId", liferayDocumentType);
Why do you use DLAppServiceUtil.updateFileEntry(...)? DLFileEntryServiceUtil has updateFileEntry method that accepts long fileEntryTypeId as a parameter.
The requirement is as follows,
When a new web content(corresponding to a particular structure, say A) is published, it should automatically get updated on the Asset Publisher portlet (default functionality of Asset Publisher).
By default the Title of the web content is what appears as a link on the Asset Publisher for different web contents.
Instead of this I want the content of an element (say name) of structure A to appear as a link. Clicking on this link should open an Alloy UI Popup containing the corresponding Web content.
For this to happen I created a new 'display style' jsp using hooks (tweaked the abstracts.jsp).
Wrote this scriptlet in the .jsp:
<%
String personName=null;
JournalArticle journalArticle=null;
String myContent=null;
Document document = null;
Node node=null;
Node node1=null;
Node node2=null;
Node node3=null;
int noOfWords=0;
String pic=null;
String aboutMe=null;
double version=0;
try {
version=JournalArticleLocalServiceUtil.getLatestVersion(assetRenderer.getGroupId(), "14405");
journalArticle = JournalArticleLocalServiceUtil.getArticle(assetRenderer.getGroupId() , "14405",version);
myContent = journalArticle.getContent();
document = SAXReaderUtil.read(new StringReader(myContent));
node = document.selectSingleNode("/root/dynamic-element[#name='personName']/dynamic-content");
if (node.getText().length() > 0) {
personName = node.getText();
}
node1 = document.selectSingleNode("/root/dynamic-element[#name='pic']/dynamic-content");
if (node1.getText().length() > 0) {
pic = node1.getText();
}
node2 = document.selectSingleNode("/root/dynamic-element[#name='noOfWords']/dynamic-content");
if (node2.getText().length() > 0) {
noOfWords = Integer.parseInt(node2.getText());
}
node3 = document.selectSingleNode("/root/dynamic-element[#name='aboutMe']/dynamic-content");
if (node3.getText().length() > 0) {
aboutMe = node3.getText(). substring(0,noOfWords)+"....";
}
} catch (PortalException e) {
e.printStackTrace();
} catch (DocumentException e) {
e.printStackTrace();
}
%>
But here the articleId needs to be hard coded.
I want to fetch the articleId here as and when a new web content is published i.e. dynamically.
Which API should be used here?
Any help is appreciated.
Thanks.
This method works for me on the latest version of Liferay - Liferay 6.1.1 CE GA2, but I think it should works without any changes on previous versions too.
Briefly, you could use getClassPK() method of the AssetEntry instance.
In all of the display jsps you get asset entry as request attribute:
AssetEntry assetEntry = (AssetEntry)request.getAttribute("view.jsp-assetEntry");
And then to get latest version of journal article that's associated with asset entry instead of using:
double version =
JournalArticleLocalServiceUtil.getLatestVersion(assetRenderer.getGroupId(),
articleId);
JournalArticle journalArticle =
JournalArticleLocalServiceUtil.getArticle(assetRenderer.getGroupId(),
articleId, version);
you could just write:
JournalArticle journalArticle =
JournalArticleLocalServiceUtil.getLatestArticle(assetEntry.getClassPK());
Hope this helps.
In SharePoint 2010, there is a new method CreateWeb in the Sites web service with the purpose to create new SharePoint sub sites. There are, however, a lot of issues with it - well, that is my experience at least. Here is the code that should utilize the web service and its method properly:
Uri site = new Uri("http://sp2010site/");
string webServicePath = "_vti_bin/Sites.asmx";
string webServiceUrl = Path.Combine(site.AbsoluteUri, webServicePath);
Sites webService = new Sites();
webService.Credentials = CredentialCache.DefaultNetworkCredentials;
webService.Url = webServiceUrl;
//the following line creates the sub site
string result = webService.CreateWeb("newsite", "New Site", "Site desc", "STS#0",
1033, true, 1033, true, 1033, true, true, true, true, true, true, true);
The following code returns Soap exception if something wrong happened (e.g. a sub site with the address "newsite" already exists, or the specified template doesn't exist).
If everything is ok, an InvalidOperation exception is fired with the message "There is an error in XML document (1, 310).", but the site is actually created!
If everything is ok, but I use my own solution instead of the non-default SharePoint template (such as the Team site, i.e. STS#0), I get a Soap exception and the site does not get created.
This has been a terrible experience so far. Please post your experiences with the sub site creation in SP 2010, and even better, post your resolutions to these problems if you have any. Cheers all!
Steps in SP2010 beta something to create a [sub] site from a [custom] template:
Activate your site template
Browse to betasoftwaresucks/_layouts/templatepick.aspx
Click on the "Custom" tab. You should be able to see your template
Open up a tool that can inspect the DOM (e.g. IE Developer Tools or Firebug). The DOM is modified dynamically so just viewing the HTML just won't work unless you're interested in one of the default templates in the default selected tab.
Find the value of the option element representing your template. It will look like "{guid}#templatename". Make sure the "Custom" tab is still open or you might not be able to find this.
Use that value as the template parameter to CreateWeb.
[I roll my SP SOAP "by hand" so it's trivial to see the full request and response.]
SharepointSiteService.Sites siteWS = new SharepointSiteService.Sites();
siteWS.Credentials = new System.Net.NetworkCredential("user1", "password", "domain");
try
{
SharepointSiteService.Template[] templates;
siteWS.GetSiteTemplates(1033, out templates);
SharepointSiteService.Template template = (from SharepointSiteService.Template t
in templates
where t.Title == "Test Template"
select t).FirstOrDefault();
siteWS.CreateWeb("<parent web name>" + "/" + <sub web name>" + "/" + <sub web name>", "Test web", "Test Web", template.Name, 1033, true, 1033, true, 1033, true, false, false, false, false, false, false);
}
catch (Microsoft.SharePoint.SoapServer.SoapServerException e)
{
System.Diagnostics.EventLog.WriteEntry("SharePoint Foundation", "soap exception" + e.Detail + e.Message + e.Source + e.Node);
}
catch (Exception ex)
{
System.Diagnostics.EventLog.WriteEntry("SharePoint Foundation", "Site Created");
System.Diagnostics.EventLog.WriteEntry("SharePoint Foundation", ex.Message + ex.Source + ex.StackTrace);
}