Wednesday, 19 November 2014

Parse csv and create contents for each row in the csv. web content managment

Usecase:- When client says he will upload a csv with contents in it. For every upload a sitearea has to be created and contents need to be placed there. Then other users will go through the approval process.

Step1 :- We need to create a custom action and apply it to publish action(Before entering the stage).Create a dynamic web project and place below plugin.xml in it.

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

<plugin id="com.Poc.workflow.CustomCopyImageWorkflow" name="Custom Copy Image Action Factory" version="1.0.0" provider-name="IBM">
<extension-point id= "CustomCopyActionFactory" name="CustomCopyActionFactory" />
<extension point="com.ibm.workplace.wcm.api.CustomWorkflowActionFactory" id= "SSPCopyImageActionFactory" >
<provider class= "com.Poc.workflow.factory.CustomFactory"/>
</extension>

</plugin>


Step 2 :-  First create a class implementing CustomWorkflowActionFactory so that you can control the workflow process.

package com.Poc.workflow.factory;

import java.util.Locale;

import com.Poc.workflow.action.CreatingContentsCustomWorkflowAction;
import com.ibm.workplace.wcm.api.Document;
import com.ibm.workplace.wcm.api.custom.CustomWorkflowAction;
import com.ibm.workplace.wcm.api.custom.CustomWorkflowActionFactory;

public class CustomFactory implements CustomWorkflowActionFactory {

 @Override
 public CustomWorkflowAction getAction(String arg0, Document arg1) {
  // TODO Auto-generated method stub
  return new CreatingContentsCustomWorkflowAction();
 }

 @Override
 public String getActionDescription(Locale arg0, String arg1) {
  // TODO Auto-generated method stub
  return "WorkFlowToCreateContentItem";
 }

 @Override
 public String[] getActionNames() {
  // TODO Auto-generated method stub
  String names[] ={"WorkFlowToCreateContentItem"};
  return names;
 }

 @Override
 public String getActionTitle(Locale arg0, String arg1) {
  // TODO Auto-generated method stub
  return "WorkFlowToCreateContentItem";
 }

 @Override
 public String getName() {
  // TODO Auto-generated method stub
  return "WorkFlowToCreateContentItem";
 }

 @Override
 public String getTitle(Locale arg0) {
  // TODO Auto-generated method stub
  return "WorkFlowToCreateContentItem";
 }

}

Step3 :- Now create your custom workflow by implementing CustomWorkflowAction

CSV PARSER
package com.Poc.workflow.action;

import java.io.InputStream;
import java.util.Date;
import java.util.List;
import java.util.logging.Logger;

import javax.naming.InitialContext;

import com.Poc.workflow.util.CsvParser;
import com.Poc.workflow.util.TimeStampUtil;
import com.ibm.workplace.wcm.api.ChildPosition;
import com.ibm.workplace.wcm.api.Content;
import com.ibm.workplace.wcm.api.ContentComponent;
import com.ibm.workplace.wcm.api.Document;
import com.ibm.workplace.wcm.api.DocumentId;
import com.ibm.workplace.wcm.api.DocumentIdIterator;
import com.ibm.workplace.wcm.api.DocumentTypes;
import com.ibm.workplace.wcm.api.FileComponent;
import com.ibm.workplace.wcm.api.NumericComponent;
import com.ibm.workplace.wcm.api.Repository;
import com.ibm.workplace.wcm.api.SiteArea;
import com.ibm.workplace.wcm.api.TextComponent;
import com.ibm.workplace.wcm.api.WCM_API;
import com.ibm.workplace.wcm.api.WebContentCustomWorkflowService;
import com.ibm.workplace.wcm.api.Workspace;
import com.ibm.workplace.wcm.api.custom.CustomWorkflowAction;
import com.ibm.workplace.wcm.api.custom.CustomWorkflowActionResult;
import com.ibm.workplace.wcm.api.custom.Directive;
import com.ibm.workplace.wcm.api.custom.Directives;

public class CreatingContentsCustomWorkflowAction implements
CustomWorkflowAction {
Logger logger = Logger.getLogger(CreatingContentsCustomWorkflowAction.class.getName());
WebContentCustomWorkflowService webContentCustomWorkflowService = null;
InitialContext initContext = null;
CustomWorkflowActionResult result = null;
Directive directive = null;
String message = null;
public static int counter =0;
@Override
public CustomWorkflowActionResult execute(Document arg0) {
Repository repository = null;
List<String[]> dataList = null;
Workspace workspace = null;
//Retrieve the csv and then create a content
if (arg0 instanceof Content) {
directive = Directives.CONTINUE;
Content content = (Content)arg0;
try{
repository = WCM_API.getRepository();
// get workspace for current user
workspace = repository.getWorkspace();
// Set library
workspace.setCurrentDocumentLibrary(workspace.getDocumentLibrary("TCP_DesignLibrary"));
//Retrieve the csv details
directive = Directives.CONTINUE;
ContentComponent cc = (ContentComponent)content.getComponent("UploadCSV");
if(cc instanceof FileComponent){
FileComponent fc = (FileComponent)cc;
InputStream inputStream = fc.getFileStream();
CsvParser csvParser = new CsvParser();
csvParser.parseFile(inputStream);
dataList =csvParser.getRows();

}
}catch(Exception exp){
exp.printStackTrace();
logger.info("Exception while retrieving image");
}


// retrieve repository
try{

// define authoring template
String authoringTemplateName = new String("TranferDirection_csvEntity_AT");
// define parent sitearea
String parentSiteAreaName = new String("TranferDirection_Row_SA");
// define workflow
String workflowName = new String("TCP_workflow");
DocumentId authoringTemplateId = null;
DocumentId parentSiteAreaId = null;
DocumentId ATSA_id = null;
DocumentId childSiteAreaId = null;
DocumentId siblingId = null;
DocumentId siteAreasiblingId = null;
DocumentId workflowId = null;
// find authoring template by name
DocumentIdIterator authoringTemplateIterator = workspace.findByName(DocumentTypes.AuthoringTemplate,authoringTemplateName);
if (authoringTemplateIterator.hasNext()){
authoringTemplateId = authoringTemplateIterator.nextId();
logger.info("Authoring Template found : " + authoringTemplateName + "<br>");
}else {
logger.info("Could not find Authoring Template: " + authoringTemplateName + "<br>");
}
// Top parent site-area by name
DocumentIdIterator siteAreaIterator = workspace.findByName(DocumentTypes.Site,parentSiteAreaName);
if (siteAreaIterator.hasNext()){
parentSiteAreaId = siteAreaIterator.nextId();
logger.info("Sitearea Found : " + parentSiteAreaName + "<br>");
}else {
logger.info("Could not find Sitearea : " + parentSiteAreaName + "<br>");
}
// find sitearea by name
DocumentIdIterator siteAreaIterator2 = workspace.findByName(DocumentTypes.SiteAreaTemplate,"ATSA_TranferDirectionTemplate");
if (siteAreaIterator2.hasNext()){
ATSA_id = siteAreaIterator2.nextId();
logger.info("Sitearea Found : " + parentSiteAreaName + "<br>");
}else {
logger.info("Could not find Sitearea : " + parentSiteAreaName + "<br>");
}
// create the sub-site area
SiteArea ss = workspace.createSiteArea(ATSA_id,parentSiteAreaId,null,ChildPosition.END);
String childSiteAreaName = "Csv"+Integer.toString(counter);
ss.setName(childSiteAreaName);
ss.setTitle(childSiteAreaName);
ContentComponent cc2 = (ContentComponent)ss.getComponent("TransferId");
if(cc2 instanceof TextComponent){
TextComponent tc = (TextComponent)cc2;
tc.setText(TimeStampUtil.timeStamp());
ss.setComponent("TransferId", (ContentComponent)tc);
}
ContentComponent cc3 = (ContentComponent)ss.getComponent("Status");
if(cc2 instanceof TextComponent){
TextComponent tc = (TextComponent)cc3;
tc.setText("Pending Store Ops");
ss.setComponent("Status", (ContentComponent)tc);
}
String[] saveMessage = workspace.save((Document)ss);
// find sub sitearea by name
DocumentIdIterator siteAreaIterator3 = workspace.findByName(DocumentTypes.SiteArea,childSiteAreaName);
if (siteAreaIterator3.hasNext()){
childSiteAreaId = siteAreaIterator3.nextId();
logger.info("Sitearea Found : " + childSiteAreaId + "<br>");
}else {
logger.info("Could not find Sitearea : " + childSiteAreaName + "<br>");
}
// find workflow by name
DocumentIdIterator workflowIterator = workspace.findByName(DocumentTypes.Workflow,workflowName);
if (workflowIterator.hasNext()){
workflowId = workflowIterator.nextId();
logger.info("Workflow found *: " + workflowName + "<br>");
}else {
logger.info("Could not find Workflow: " + workflowName + "<br>");
}

if((authoringTemplateId!=null) && (parentSiteAreaId!=null) && (workflowId!=null)){
for (String[] strings : dataList) {
// create new content
counter=counter+1;
Content newContent = workspace.createContent(authoringTemplateId,childSiteAreaId,siblingId,ChildPosition.END);
newContent.setName("TransferDirection_Content"+Integer.toString(counter));
newContent.setTitle("NewContent_csv_row"+Integer.toString(counter));
newContent.setDescription("New Content created for individual css");
newContent.setWorkflowId(workflowId);

ContentComponent contentComponent = newContent.getComponent("Sending");
if(contentComponent instanceof TextComponent){
TextComponent tc = (TextComponent)contentComponent;
logger.info("First element :-"+tc.getName());
tc.setText(strings[0]);
logger.info("First element content :-"+tc.getText());
newContent.setComponent("Sending", (ContentComponent)tc);
}


ContentComponent contentComponent2 = newContent.getComponent("Recieving");
if(contentComponent2 instanceof TextComponent){
TextComponent tc2 = (TextComponent)contentComponent2;
logger.info("Second element :-"+tc2.getName());
tc2.setText(strings[1]);
logger.info("Second element content :-"+tc2.getText());
newContent.setComponent("Recieving", (ContentComponent)tc2);
}

ContentComponent contentComponent3 = newContent.getComponent("Qty");
if(contentComponent3 instanceof NumericComponent){
NumericComponent tc3 = (NumericComponent)contentComponent3;
logger.info("Third element :-"+tc3.getName());
tc3.setNumber(Integer.parseInt(strings[2]));
logger.info("Third element content :-"+tc3.getNumber());
newContent.setComponent("Qty", (ContentComponent)tc3);
}

String[] saveMessage2 = workspace.save((Document)newContent);
logger.info("Save message :- "+saveMessage2.toString());
if (saveMessage2.length==0) {
logger.info (" <BR> Created new Content under " + childSiteAreaName );
}

}
}else {
logger.info ("Could not create new content");
}
}catch(Exception e){
e.printStackTrace();
}

}

//Logic whether to navigate to other stage or not
try {
initContext = new InitialContext();
webContentCustomWorkflowService = (WebContentCustomWorkflowService) initContext.lookup("portal:service/wcm/WebContentCustomWorkflowService");
result = webContentCustomWorkflowService.createResult(directive,message);
logger.info("Getting base wcm service");
} catch (Exception ex) {
message = "An exception has occured in ex " + ex.getMessage();
directive = Directives.ROLLBACK_DOCUMENT;
ex.printStackTrace();
}

return result;
}

@Override
public Date getExecuteDate(Document arg0) {
// TODO Auto-generated method stub
return DATE_EXECUTE_NOW;
}

}

Step4 :- Create all utility classes needed for it

package com.Poc.workflow.util;

import java.io.BufferedReader;


public class CsvParser {
private int rowCount; // Number of rows (excluding header row)

private int fieldCount; // Number of fields in each row

private String[] headers; // Field names (assumed to be in first row)

private List<String[]> rows = new ArrayList<String[]>(); // The data

public CsvParser() {
// Must have a no-argument constructor as a bean.
}

public void parseFile(InputStream inputStream) {

BufferedReader br;
try {
br = new BufferedReader(new InputStreamReader(inputStream));
} catch (Exception e) {
e.printStackTrace();
return;
}
String line;
boolean firstRow = true;
try {
while ((line = br.readLine()) != null) {
//Parsing Csv
if (firstRow) {
headers = tokenize(line);
setFieldCount(headers.length);
firstRow = false;
}else{
String[] row = tokenize(line);
rows.add(row);  
rowCount++;
}
}
} catch (IOException e1) {
e1.printStackTrace();
return;
}
}

protected String[] tokenize(String line) {
StringTokenizer st = new StringTokenizer(line, ",");
int tokenCount = st.countTokens();
String[] record = new String[tokenCount];
for (int i = 0; i < tokenCount; i++) {
record[i] = (String) st.nextToken();
}
return record;
}

public int getFieldCount() {
return fieldCount;
}

public void setFieldCount(int fieldCount) {
this.fieldCount = fieldCount;
}

public String[] getHeaders() {
return headers;
}

public void setHeaders(String[] headers) {
this.headers = headers;
}

public int getRowCount() {
return rowCount;
}

public void setRowCount(int rowCount) {
this.rowCount = rowCount;
}

public List getRows() {
return rows;
}

public void setRows(List rows) {
this.rows = rows;
}

public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("Headers: ");
addStringArray(headers, sb);
Iterator it = rows.iterator();
int rowCount = 0;
while (it.hasNext()) {
rowCount++;
sb.append("Row " + rowCount + ": ");
String[] row = (String []) it.next();
addStringArray(row, sb);
}
return sb.toString();
}

protected StringBuffer addStringArray(String[] array, StringBuffer buffer) {
for (int i = 0; i < array.length; i++) {
buffer.append(array[i] + ",");
}
buffer.append("\n");
return buffer;
}


}

 Timestamp utility

package com.Poc.workflow.util;

import java.sql.Timestamp;


public class TimeStampUtil
{
    public static String timeStamp()
    {
java.util.Date date= new java.util.Date();
Timestamp tm = new Timestamp(date.getTime());
System.out.println(tm.toString());
return tm.toString();
    }
   
 
}

Step 5 :- Deploy this war file and go to web content management and map custom action. Refere to my previous custom email action blog for help in mapping actions.

Mixing Personalization, Personalized list portlet and web content management

Overview :- We will make a personalization rule which retrieves content from selected Authoring template and selected sitearea{These selections you can change based on ur requirement}. Now we will display them in a personalized portlet.

Usecase :- You can use above approach to show particular content based on your rule. This you can classify as alternative for webcontent viewer portlet in some case.

Step 1 :- Create Authoring template,sitearea,content and presentation temple. Now we will apply personalization such that content displayed in portlet is from a particular sitearea and belong to a particular authoring template.

Step 2 :- Navigate to portal administration->applications-business rule and create a rule as given below


   Rule Type :- Do not select anything
   Location :- Select your site area
   Select Authoring Template as key and value as your Authoring Template

Step3 :- Save it then you can click on preview to view the result


Step 4 :- Now we have to configure Personalization portlet to this rule.Navigate to Applications->Personalization-> Personalized List then click edit mode and click on configure option.


 Personalization resources :- Select your rule from here

Step 5 :-  Specifying display options by clicking on it. Basically from here you can control the way content is displayed and how it is organized.


  Title :- Displays title for each row of data displayed in portlet.
  Categorization :- Category displayed at the top of all rows.

Step 6 :- Click ok to see the content


   Title :- CT_PersonalizationContent
  Categorization :- Other.

Conclusion :- Using these portlet we can configure global content which can be modified by changing the rule. Content shown here will be same for all users because configurations are made at config level.

Monday, 17 November 2014

Exporting and importing wcm library

Use-case :-  You have developed a module in WCM by creating custom library. Now you want to share it with other developer. We need to export the library from one machine to another machine.

Step1 :-  We need to set the library which we want to export in WCMConfigService in your was administration.


Step 2 :- Set export.libraryname to the library you want to export.

Step 3 :- Execute below config engine task under wp_profile

ConfigEngine.bat export-wcm-data -DWasPassword=pAssw0rd321 -DPortalAdminPwd=pAssw0rd321

Step 4 :- Now you can find exported library under {C:\IBM\WebSphere\wp_profile\PortalServer\wcm\ilwwcm\system\export} this path


Step 5 :- In other machine set import.directory  in WCMConfigService and run below task

ConfigEngine.bat import-wcm-data -DWasPassword=pAssw0rd321 -DPortalAdminPwd=pAssw0rd321



Hidden pages in websphere portal8

Hidden Pages :- Pages created under  'Hidden Pages' label are hidden from page navigation.



Use-case :- If you dont want to show a particular page in navigation but you want to reach it out through friendly url.

1) Go to Administration, Manage Pages

2) Export the page to be hidden.

3) Edit the pageExport.xml. Add the line below.

<parameter name="com.ibm.portal.Hidden" type="string" update="set"><![CDATA[true]]></parameter>

4) Go to Adminitration, Import XML. Import the xml with the new line. Before importing please delete previous page which you have exported.


Sunday, 16 November 2014

Profiling dojo to load specific modules

Profiling dojo

1) Download latest source code of dojo version you were using make sure it has util folder inside it.

2) Now you have to make your custom profile and place it under profiles folder then run the build tool.

3) Creating new profile  :-

dependencies = {
            //Strip all console.* calls except console.warn and console.error. This is basically a work-around
            //for trac issue: http://bugs.dojotoolkit.org/ticket/6849 where Safari 3's console.debug seems
            //to be flaky to set up (apparently fixed in a webkit nightly).
            //But in general for a build, console.warn/error should be the only things to survive anyway.
            stripConsole: "normal",

            selectorEngine:"acme",

            layers: [
                        {
                                    name: "../dijit/dijit.js",
                                    dependencies: [
                                                "dijit.dijit"
                                    ]
                        },         
                       
                        {
                                    name: "dojo.js",
                                    dependencies: [
                                "dojo.loadInit",
                                                                                                "dojo.text",
                                                                                                "dojo.i18n",
                                                                                                "dojo/_base/declare",
                                "dojo.parser",                                                                                        
                                                                                                "dojo/dom",
                                                                                                "dijit.dijit",
                                "dijit.layout.ContentPane",
                                "dijit.layout.TabContainer",
                                "dijit.layout.BorderContainer",
                                "dijit.form.ComboBox",
                                "dijit.form.Button",
                                "dijit.form.TextBox",                          
                                "dojox.widget.Portlet",
                                                                                                "dojo.data.ItemFileReadStore",
                                "dojo.data.ItemFileWriteStore", 
                                                                                                "dojox.grid.DataGrid",
                                "dojox.grid.EnhancedGrid",
                                                                                                "dojox.grid.enhanced.plugins.IndirectSelection",
                                "dojox.grid.enhanced.plugins.Pagination",
                                "dijit.TitlePane",                             
                                "dijit.form.RadioButton",
                                "dijit.form.SimpleTextarea",                                
                                "dojox.dtl",                                                   
                                "dojox.dtl.Context",
                                "dijit.Editor",                               
                                "dijit.form.Form",
                                                                                                "dijit/form/ValidationTextBox",
                                                                                                "dijit/form/CheckBox",
                                                                                                "dijit/form/Button",
                                                                                                "dijit/form/NumberTextBox",
                                                                                                "dijit.form.DateTextBox",
                                "dijit.form.Select",
                                "dojox/grid/enhanced/plugins/Cookie",
                                                                                                "dojox.html.entities",
                                "dojox.html.ellipsis",
                                                                                                "dijit/MenuBar",
                                                                                                "dijit/PopupMenuBarItem",
                                                                                                "dijit/MenuItem",
                                                                                                "dijit/Menu",
                                                                                                "dojox/validate/web",
                                                                                                "dojo/io/iframe",
                                                                                                "dojox/data/QueryReadStore",
                                                                                                "dijit/form/FilteringSelect"
                                                                                               
                                    ]
                        }
                       
            ],

            prefixes: [
                        [ "dijit", "../dijit" ],
                        [ "dojox", "../dojox" ]
            ]



}

4)Build tool command: -

build.bat action=release,clean profile="C:\Users\Administrator\Desktop\DojoProfiling\dojo-release-1.8.0-src\dojo-release-1.8.0-src\util\buildscripts\profiles\dtna.profile.js" cssOptimize=comments.keepLines releaseDir=dtnadojo optimize=shrinksafe

5) Copy the profiled dojo.js and place it in your project.

References: -
http://dojotoolkit.org/reference-guide/1.8/build/buildScript.html

https://dojotoolkit.org/reference-guide/1.8/build/profiles.html


Working with WCM navigator component


Usecase :- Think you have a requirement for a links to be dynamically coming from a site-area and these links will be edited  by business people.

Step1 :-  Create your site-areas hierarchy as you decide. Now create your navigator component and use below code. Then map it to Content,Authoring template and Presentation template.

Result design 1:-
<li class="menuListItems level1Menu wpthemeLeft">
 <a target="_blank" href="[Element context="autofill" type="sitearea" key="LinkElement" format="url"]" class="mainMenuA">
  <div class="customTitle">
   <span class="menuTitle">[Placeholder tag="title"]</span>
  </div>
 </a>

Result design 2 :-
<ul class="wpthemeNavList submenu level2Menu hiddenDisplay">

<li class="wpthemeNavListItem wpthemeLeft">
 <a target="_blank" class="wpthemeLeft wpthemeFirst" href="[Element context="autofill" type="sitearea" key="LinkElement" format="url"]">
  [Placeholder tag="title"]
 </a>

</ul>
</li>

Result design 3 :-
<ul class="wpthemeNavList level4Menu">

<li class="wpthemeNavListItem">
 <a target="_blank" class="wpthemeLeft wpthemeFirst" href="[Element context="autofill" type="sitearea" key="LinkElement" format="url"]">
  [Placeholder tag="title"]
 </a>
</li>

</ul>
</li>

Step 2 :- Now create web-content-viewer portlet and map navigator to show navigation.


Saturday, 8 November 2014

Exploring Language support in websphere portal8

Language support :-  Websphere portal supports multiple languages because portal can be used any country. It can even have some portlets in Japanese and some portlets in English.

WebSphere Portal has already been translated into a number of languages. They are shown in the following list, together with the ISO 639 language codes. These codes are used for the languages in WebSphere Portal:

WebSphere Portal language codes(32 languages): -

  • ar     =   Arabic, ca     =   Catalan, cs     =   Czech, da     =   Danish, nl     =   Dutch
  • en     =   English, fi     =   Finnish, fr     =   French, de     =   German , el     =   Greek
  • iw     =   Hebrew, hr     =   Croatian, hu     =   Hungarian, it     =   Italian,
  • ja     =   Japanese, kk     =   Kazakh,  ko     =   Korean,  no     =   Norwegian
  • pl     =   Polish , pt     =   Portuguese, pt_BR =   Brazilian Portuguese, ro     =   Romanian
  • ru     =   Russian, sk     =   Slovak, sl     =   Slovenian. es     =   Spanish
  • zh     =   Simplified Chinese, zh_TW =   Traditional Chinese, sv     =   Swedish
  • th     =   Thai, tr     =   Turkish, uk     =   Ukrainian
Usecase (Now we got a client from Maldives(dv-MV) we need to make a portal for them how will you add a new language bundle to portal) :-  

Step 1 :- In WebSphere® Portal, resource bundles are located in the JAR files wp.ui.jar and wp.theme.customizer.ext.jar in the nls directory inside the file. 

The JAR file wp.ui.jar is located under the following directory:
Windows: PortalServer_root\ui\wp.ui\shared\app

The JAR file wp.theme.customizer.ext.jar is located under the following directory:
Windows: PortalServer_root\theme\wp.theme.customizer.ext\shared\app

Step 2 :-
If you want to add new resource bundles for additional languages, place them into the following directory:
Windows: wp_profile_root\PortalServer\config\nls
The naming convention for resource bundles is [bundle]_ [language]_ [country]_ [variant].properties . WebSphere Portal supports the use of [variant], although resource bundles supplied with the portal do not use it.

Note: If your portal configuration includes Lotus Collaborative Services, add a new CSRes_language.properties file for each additional language to the following directory:
Windows: wp_profile_root\PortalServer\config\nls

Step 3 :-
Copy all existing resource bundles into wp_profile_root/PortalServer/config/nls directory.
Name the resource bundles according to the naming convention for resource bundles using locale code for the language(s) installed. Translate the resource bundle files. Convert them into Unicode with the Native-to-ASCII converter native2ascii which comes as part of JDK. For more detail about native2ascii see the Java documentation native2ascii - Native-to-ASCII Converter.

Restart your WebSphere Portal so that ir recognizes the new resource bundles.Resource bundles to support a Portal8.0 based custom theme

Step 4 :-
You can add a new supported locale to the system. To do so you must provide resource bundles for the new language to the Portal8.0 based custom theme.

Run the following XML to create the "Vietnamese" language by going to Administration -> Portal Settings -> Import XML.
<?xml version="1.0" encoding="UTF-8"?>
<request xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
type="update" 
xsi:noNamespaceSchemaLocation="PortalConfig_7.0.0.xsd">
<portal action="locate">
<language action="update" bidi="false" domain="rel" locale="vi">
<localedata locale="en">
<title>Vietnamese</title>
</localedata>
</language>
</portal>
</request>

Step 5 :- 
Copy the contents of the following files from your Portal server into a new file called language_vi.js:
PortalServer_root/theme/wp.theme.modules/webapp/installedApps/ThemeModules.ear/ThemeModules.war/modules/pagebuilder/js/nls/pb_ui_layer_en.js
PortalServer_root/theme/wp.theme.modules/webapp/installedApps/ThemeModules.ear/ThemeModules.war/modules/portalclient/js/nls/rest_utils_en.js
If you use Active Site Analytics PortalServer_root/theme/wp.theme.modules/webapp/installedApps/ThemeModules.ear/ThemeModules.war/modules/asa/js/nls/asa_layer_en.js
If you use Tagging and Rating PortalServer_root/theme/wp.theme.modules/webapp/installedApps/ThemeModules.ear/ThemeModules.war/modules/portalclient/js/nls/tagging_rating_en.js

In the language_vi.js file, replace all instances of:
en")  with:  vi")

and all instances of:
.en=  with:  .vi=

Step 6 :-
Place the language_vi.js file into the js folder of your custom theme. 
For example, dav:fs-type1/themes/custom_theme/js.
Create a theme module for the language_vi.js file by creating a languages.json file with the following contents:
{
"modules": [{
"id":"custom_languages",
"prereqs": [{
"id":"dojo"
}],
"contributions": [{
"type":"head",
"sub-contributions": [{
"type":"js",
"uris": [{
"value":"/js/language_vi.js",
"lang":"vi"
}]
}]
}]
}]
}

Step 7:- 
Place languages.json into the contributions folder of your custom theme. 
For example, dav:fs-type1/themes/custom_theme/contributions.
Add "custom_languages" as the first module in the section that includes Dojo for each profile in your custom theme. 

For example, in the Portal8.0 theme, the "custom_languages" module would be added to the "moduleIDs" section of the Full profile and the "deferredModuleIDs" section of the Deferred profile.



Custom single threaded java server

 package com.diffengine.csv; import java.io.*; import java.net.*; import java.util.Date; public class Server { public static void main(Str...