tag:blogger.com,1999:blog-25714574458426248112024-03-13T20:24:44.838-07:00Krutik JayswalAlfresco Certified EngineerKrutik Jayswalhttp://www.blogger.com/profile/16691396948811505379noreply@blogger.comBlogger25125tag:blogger.com,1999:blog-2571457445842624811.post-81111551639266353442023-08-27T08:45:00.001-07:002023-08-27T22:55:39.616-07:00Things to know when you are dealing with Apache Spark<div style="text-align: justify;">Apache spark is an interesting big data framework using which we can do amazing things when we are dealing with big data.In journey of learning spark many developers face difficulties when to use java and when to use spark framework.There where plenty of scenarios In the journey of development there scenarios where it was effcient/effective to use java instead of using spark.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">
Spark is needed in a place where there are complex and manipulative operation on large dataset.A simple case where only lifting and shiftin of data is there in that case it can be achieved using other technologies also.Let's review the certain pointers which I have learned during the spark application development.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><span style="color: #800180; font-size: large;"><b>Packging spark application using Java</b></span></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><div style="--_pr-img-mb: 0; background-color: white; border: 0px; box-sizing: inherit; clear: both; color: #232629; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI Adjusted", "Segoe UI", "Liberation Sans", sans-serif; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-size: 15px; font-stretch: inherit; font-variant-alternates: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; font-variation-settings: inherit; line-height: inherit; margin: 0px 0px 1.1em; padding: 0px; text-align: left; vertical-align: baseline;"><div style="text-align: justify;">Using maven shade plugin is not encouraged, unless and until there is no other option apart from using the maven shade plugin. Below is the informative link for not to use the shade plugin.</div><div style="--_li-fc-hover: var(--theme-link-color-hover); --_li-fc-visited: var(--theme-link-color-visited); --_li-fc: var(--theme-link-color); border: 0px; box-sizing: inherit; cursor: pointer; font-family: inherit; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-variation-settings: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-align: justify; user-select: auto; vertical-align: baseline;"><a href="https://stackoverflow.com/questions/53710931/downsides-of-using-shade-plugin-relocation-feature" style="--_li-fc-hover: var(--theme-link-color-hover); --_li-fc-visited: var(--theme-link-color-visited); --_li-fc: var(--theme-link-color); border: 0px; box-sizing: inherit; cursor: pointer; font-family: inherit; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-variation-settings: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; user-select: auto; vertical-align: baseline;">Downsides of using Shade plugin relocation feature</a></div><div style="text-align: justify;">From my perspective for running spark application, spring boot maven plugin is the best option for managing everything, including library dependencies. Even if your application is used as a scheduled job, in which you need to use spark-submit/spark launcher for launching the application.</div><div style="text-align: justify;">In other case where your java app using spark and spring both but have controller/api to use the application in that case also spring boot maven plugin is the best one.</div><div style="text-align: justify;">There are only 2 types of Challanges when we use spark-submit/spark launcher to launch the application which is created using spring boot maven plugin.</div></div><p style="--_pr-img-mb: 0; background-color: white; border: 0px; box-sizing: inherit; clear: both; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI Adjusted", "Segoe UI", "Liberation Sans", sans-serif; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-size: 15px; font-stretch: inherit; font-variant-alternates: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; font-variation-settings: inherit; line-height: inherit; margin: 0px 0px 1.1em; padding: 0px; text-align: left; vertical-align: baseline;"><strong style="border: 0px; box-sizing: inherit; font-family: inherit; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-variation-settings: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span style="color: #800180;">1. Main Class</span></strong></p><p style="--_pr-img-mb: 0; background-color: white; border: 0px; box-sizing: inherit; clear: both; color: #232629; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI Adjusted", "Segoe UI", "Liberation Sans", sans-serif; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-size: 15px; font-stretch: inherit; font-variant-alternates: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; font-variation-settings: inherit; line-height: inherit; margin: 0px 0px 1.1em; padding: 0px; text-align: left; vertical-align: baseline;">When we package fat jar/uber jar using spring boot maven plugin, it is packging the class files and java libraries in spring way and not the way sprak is expecting it.Inside the uber jar generated by the spring boot maven plugin, we have <em style="border: 0px; box-sizing: inherit; font-family: inherit; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-stretch: inherit; font-variant: inherit; font-variation-settings: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">boot-inf,meta-inf <em style="border: 0px; box-sizing: inherit; font-family: inherit; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-stretch: inherit; font-variant: inherit; font-variation-settings: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">and</em> org</em> folder.So when we give mainclass in spark submit or spark launcher as a parameter,It will not able to find that class as it will not be able to locate package/path specified in parameter, due to change of structure in jar file.Even after you specify the correct location which is starting with BOOT-INF for main class, it will not work because the way spring launches the application is using differrent main class.</p><p style="--_pr-img-mb: 0; background-color: white; border: 0px; box-sizing: inherit; clear: both; color: #232629; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI Adjusted", "Segoe UI", "Liberation Sans", sans-serif; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-size: 15px; font-stretch: inherit; font-variant-alternates: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; font-variation-settings: inherit; line-height: inherit; margin: 0px 0px 1.1em; padding: 0px; text-align: left; vertical-align: baseline;">Below is the link which shows main class that should be used for launching the fat jar generated by spring boot maven plugin.</p><p style="--_pr-img-mb: 0; background-color: white; border: 0px; box-sizing: inherit; clear: both; color: #232629; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI Adjusted", "Segoe UI", "Liberation Sans", sans-serif; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-size: 15px; font-stretch: inherit; font-variant-alternates: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; font-variation-settings: inherit; line-height: inherit; margin: 0px 0px 1.1em; padding: 0px; text-align: left; vertical-align: baseline;"><a href="https://docs.spring.io/spring-boot/docs/current/reference/html/executable-jar.html#appendix.executable-jar.launching" rel="nofollow noreferrer" style="--_li-fc-hover: var(--theme-link-color-hover); --_li-fc-visited: var(--theme-link-color-visited); --_li-fc: var(--theme-link-color); border: 0px; box-sizing: inherit; cursor: pointer; font-family: inherit; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-variation-settings: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; user-select: auto; vertical-align: baseline;">https://docs.spring.io/spring-boot/docs/current/reference/html/executable-jar.html#appendix.executable-jar.launching</a></p><p style="--_pr-img-mb: 0; background-color: white; border: 0px; box-sizing: inherit; clear: both; color: #232629; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI Adjusted", "Segoe UI", "Liberation Sans", sans-serif; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-size: 15px; font-stretch: inherit; font-variant-alternates: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; font-variation-settings: inherit; line-height: inherit; margin: 0px 0px 1.1em; padding: 0px; text-align: left; vertical-align: baseline;">On high level if I inform ,File named as MANIFEST.MF inside the uber jar contains below entries.Where <em style="border: 0px; box-sizing: inherit; font-family: inherit; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-stretch: inherit; font-variant: inherit; font-variation-settings: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Main-Class</em> is the actual main class which is used for initialization of spring related stuff, after which customized main class should get started which is Start-Class entry.</p><p style="--_pr-img-mb: 0; background-color: white; border: 0px; box-sizing: inherit; clear: both; color: #232629; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI Adjusted", "Segoe UI", "Liberation Sans", sans-serif; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-size: 15px; font-stretch: inherit; font-variant-alternates: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; font-variation-settings: inherit; line-height: inherit; margin: 0px 0px 1.1em; padding: 0px; text-align: left; vertical-align: baseline;">Main-Class: org.springframework.boot.loader.JarLauncher Start-Class: com.mycompany.project.MyApplication</p><p style="--_pr-img-mb: 0; background-color: white; border: 0px; box-sizing: inherit; clear: both; color: #232629; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI Adjusted", "Segoe UI", "Liberation Sans", sans-serif; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-size: 15px; font-stretch: inherit; font-variant-alternates: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; font-variation-settings: inherit; line-height: inherit; margin: 0px 0px 1.1em; padding: 0px; text-align: left; vertical-align: baseline;">So as a conclusion specifiying main class as "<strong style="border: 0px; box-sizing: inherit; font-family: inherit; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-variation-settings: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">org.springframework.boot.loader.JarLauncher</strong>" in spark-submit or spark-launcher will resolve our issue for this problem.This will only work if you are using sparing boot maven plugin for packagin the jar.</p><p style="--_pr-img-mb: 0; background-color: white; border: 0px; box-sizing: inherit; clear: both; color: #232629; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI Adjusted", "Segoe UI", "Liberation Sans", sans-serif; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-size: 15px; font-stretch: inherit; font-variant-alternates: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; font-variation-settings: inherit; line-height: inherit; margin: 0px 0px 1.1em; padding: 0px; text-align: left; vertical-align: baseline;"><strong style="border: 0px; box-sizing: inherit; font-family: inherit; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-variation-settings: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">External common libraries used in pom.xml+spark installation.</strong> Another issue which might occure while using spark-submit or launcher application while launching uber jar, packaged using the spring boot maven plugin is jar conflicts.So the problem will be when we package jar using spring boot maven plugin, it is coping depedencies inside BOOT-INF/lib folder, let's say if you are using below depedency in pom.xml.</p><pre class="lang-xml s-code-block" style="--_cb-line-numbers-bg: var(--black-050); border-radius: var(--br-md); border: 0px; box-sizing: inherit; color: var(--highlight-color); font-family: var(--ff-mono); font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-size: var(--fs-body1); font-stretch: inherit; font-variant-alternates: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; font-variation-settings: inherit; line-height: var(--lh-md); margin-bottom: calc(1.5em); margin-top: 0px; max-height: 600px; overflow-wrap: normal; overflow: auto; padding: var(--su12); text-align: left; vertical-align: baseline; width: auto;"><code class="hljs language-xml" style="border: 0px; box-sizing: inherit; font-family: inherit; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-size: var(--_pr-code-fs); font-stretch: inherit; font-style: inherit; font-variant: inherit; font-variation-settings: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline; white-space: inherit;"><span class="hljs-tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-size: 13px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-variation-settings: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><<span class="hljs-name" color="var(--highlight-namespace)" style="border: 0px; box-sizing: inherit; font-family: inherit; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-variation-settings: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">dependency</span>></span>
<span class="hljs-tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-size: 13px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-variation-settings: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><<span class="hljs-name" color="var(--highlight-namespace)" style="border: 0px; box-sizing: inherit; font-family: inherit; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-variation-settings: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">groupId</span>></span>com.google.code.gson<span class="hljs-tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-size: 13px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-variation-settings: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"></<span class="hljs-name" color="var(--highlight-namespace)" style="border: 0px; box-sizing: inherit; font-family: inherit; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-variation-settings: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">groupId</span>></span>
<span class="hljs-tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-size: 13px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-variation-settings: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><<span class="hljs-name" color="var(--highlight-namespace)" style="border: 0px; box-sizing: inherit; font-family: inherit; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-variation-settings: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">artifactId</span>></span>gson<span class="hljs-tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-size: 13px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-variation-settings: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"></<span class="hljs-name" color="var(--highlight-namespace)" style="border: 0px; box-sizing: inherit; font-family: inherit; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-variation-settings: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">artifactId</span>></span>
<span class="hljs-tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-size: 13px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-variation-settings: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><<span class="hljs-name" color="var(--highlight-namespace)" style="border: 0px; box-sizing: inherit; font-family: inherit; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-variation-settings: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">version</span>></span>2.10<span class="hljs-tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-size: 13px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-variation-settings: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"></<span class="hljs-name" color="var(--highlight-namespace)" style="border: 0px; box-sizing: inherit; font-family: inherit; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-variation-settings: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">version</span>></span>
<span class="hljs-tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-size: 13px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-variation-settings: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"></<span class="hljs-name" color="var(--highlight-namespace)" style="border: 0px; box-sizing: inherit; font-family: inherit; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-variation-settings: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">dependency</span>></span>
</code></pre><p style="--_pr-img-mb: 0; background-color: white; border: 0px; box-sizing: inherit; clear: both; color: #232629; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI Adjusted", "Segoe UI", "Liberation Sans", sans-serif; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-size: 15px; font-stretch: inherit; font-variant-alternates: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; font-variation-settings: inherit; line-height: inherit; margin: 0px; padding: 0px; text-align: left; vertical-align: baseline;">Now let's say this depedency already exist with differrent version in spark installation, in that case it will give conflict in classes.As it will be an issue of class loader ,its better not to use those which might create conflict due to which application might fail.I have faced this kind of issues related to logger classes or json libraries, as there are multiple json/logger library options are available.As a resolution you can excluded those classes or libraries or you can replace that library with alternative one.</p></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><span style="color: #800180; font-size: large;"><b>Deployment/Triggering Spark Applciation</b></span></div><div style="text-align: justify;"><span style="font-weight: normal;"><span style="font-size: medium;"><br /></span></span></div><div>There are plenty of ways using which we can trigger or deploy the application in spark server.We will see two scenarios using which we can use the spark in the application development.</div><div><span style="font-size: large; text-align: justify;"><br /></span></div><div><span style="text-align: justify;"><span style="color: #800180; font-size: large;">Deploy as Job In kubernates cluster</span></span></div><div><span style="text-align: justify;"><span style="font-size: medium;"><br /></span></span></div><div><span style="text-align: justify;">We can deploy the spark application as a job in kubermates cluster.If we choose to deploy application using this approach , in that case, main method will be triggered if you are using java.Because that is the entry point of the application.The application will not be running 24*7 , we can schdule this application in kubernates cluster as well to periodically trigger the job.In this case we can use below command to trigger the spark job.</span>
<pre class="brush: java" name="java">
./bin/spark-submit \
--master <master-url> \
--deploy-mode <deploy-mode> \
--conf <key<=<value> \
--driver-memory <value>g \
--executor-memory <value>g \
--executor-cores <number of cores> \
--jars <comma separated dependencies>
--class <main-class> \
<application-jar> \
[application-arguments]
</pre>
</div><div><span style="text-align: justify;"><br /></span></div><div><span style="text-align: justify;"><br /></span></div><div><br /></div><div><span style="text-align: justify;"><br /></span></div><div><span style="text-align: justify;"><br /></span></div><div style="text-align: justify;"><span style="color: #800180; font-size: large;">Deploy as Rest In kubernates cluster</span></div><div style="text-align: justify;">Another way to trigger the business logic of the spark aplication is to have one rest application deployed and running in the cluster.Using that application we will be ablt to trigger the business logic or the task.In this case we can pass the job parameter as the url parameter in to the rest api application.Below is sample code for same.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">
<pre class="brush: java" name="java">
curl -X POST [http://sparkendpoint.com]/v1/submissions/create --header "Content-Type:application/json;charset=UTF-8" --data '{
"appResource": "file:/home/user/spark_pi.py",
"sparkProperties": {
"spark.executor.memory": "8g",
"spark.master": "spark://192.168.1.1:7077",
"spark.driver.memory": "8g",
"spark.driver.cores": "2",
"spark.eventLog.enabled": "false",
"spark.app.name": "Spark REST API - PI",
"spark.submit.deployMode": "cluster",
"spark.driver.supervise": "true"
},
"clientSparkVersion": "2.4.0",
"mainClass": "org.apache.spark.deploy.SparkSubmit",
"environmentVariables": {
"SPARK_ENV_LOADED": "1"
},
"action": "CreateSubmissionRequest",
"appArgs": [ "/home/user/spark_pi.py", "80" ]
}'
</pre>
</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div class="blogger-post-footer">https://scontent-b-mxp.xx.fbcdn.net/hphotos-xap1/v/t1.0-9/10675541_896261013719814_5601513019470361090_n.jpg?oh=741b05a81becaae8bce36db141948a4a&oe=5531762A</div>Krutik Jayswalhttp://www.blogger.com/profile/16691396948811505379noreply@blogger.com0tag:blogger.com,1999:blog-2571457445842624811.post-30831221189610853062021-04-24T11:26:00.002-07:002021-04-24T12:53:54.589-07:00Builder Design Patterns<div style="text-align: justify;">This is one of the easiest and interesting design pattern among other creational design pattern. With use of builder design pattern we can create and object by passing several optional parameters. If the object creation is complex and it requires several parameters for creating an object in that case we can use the builder pattern for creating an object.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">Idea of using the builder pattern is we initially create the blank object with no parameters or with the minimum number of parameter and letter on we will add the optional parameter whenever required and will return the created object. In java StringBuffer and StringBuilder objects are created using the builder pattern.</div><div style="text-align: justify;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-F0GghEgsa2o/YIRXFb2KOwI/AAAAAAAAhyQ/5CnUtXk8NKQyPwhcv6JeyuCimKJnBxsUQCLcBGAsYHQ/s1040/BuilderDesignPattern.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="762" data-original-width="1040" src="https://1.bp.blogspot.com/-F0GghEgsa2o/YIRXFb2KOwI/AAAAAAAAhyQ/5CnUtXk8NKQyPwhcv6JeyuCimKJnBxsUQCLcBGAsYHQ/s16000/BuilderDesignPattern.png" /></a></div><br /><div style="text-align: justify;"><br /></div><div style="text-align: justify;">As image describes using HouseBuilder class we can directly create the object of furnished or unfurnished house without exposing the complex object creation login. Let's check the example with code.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><div><b>House.java</b></div>
<div><pre class="brush: java" name="java"> package com.design.pattern.builder;
public class House {
private String window;
private String door;
private String bathroom;
private String bedroom;
private String furniture;
public String getWindow() {
return window;
}
public void setWindow(String window) {
this.window = window;
}
public String getDoor() {
return door;
}
public void setDoor(String door) {
this.door = door;
}
public String getBathroom() {
return bathroom;
}
public void setBathroom(String bathroom) {
this.bathroom = bathroom;
}
public String getBedroom() {
return bedroom;
}
public void setBedroom(String bedroom) {
this.bedroom = bedroom;
}
public String getFurniture() {
return furniture;
}
public void setFurniture(String furniture) {
this.furniture = furniture;
}
@Override
public String toString() {
return "House has "+this.bedroom+", " +this.bathroom+", "+this.getDoor()+", "+this.getWindow()+ (this.getFurniture()!=null?", "+this.getFurniture():"");
}
}
</pre></div>
<div><b>FurnishedHouseBuilder.java</b></div>
<div><pre class="brush: java" name="java"> package com.design.pattern.builder;
public class FurnishedHouseBuilder {
private House house;
public House getHouse() {
return house;
}
public void setHouse(House house) {
this.house = house;
}
public FurnishedHouseBuilder() {
house = new House();
}
public FurnishedHouseBuilder buildWindow() {
house.setWindow("window");
return this;
}
public FurnishedHouseBuilder buildDoor() {
house.setDoor("door");
return this;
}
public FurnishedHouseBuilder buildBedroom() {
house.setBedroom("bedroom");
return this;
}
public FurnishedHouseBuilder buildBathRoom() {
house.setBathroom("bathroom");
return this;
}
public FurnishedHouseBuilder buildFurniture() {
house.setFurniture("furniture");
return this;
}
}
</pre></div>
<div><b>UnfurnishedHouseBuilder.java</b></div>
<div><pre class="brush: java" name="java"> package com.design.pattern.builder;
public class UnfurnishedHouseBuilder {
private House house;
public House getHouse() {
return house;
}
public void setHouse(House house) {
this.house = house;
}
public UnfurnishedHouseBuilder() {
house = new House();
}
public UnfurnishedHouseBuilder buildWindow() {
house.setWindow("window");
return this;
}
public UnfurnishedHouseBuilder buildDoor() {
house.setDoor("door");
return this;
}
public UnfurnishedHouseBuilder buildBedroom() {
house.setBedroom("bedroom");
return this;
}
public UnfurnishedHouseBuilder buildBathRoom() {
house.setBathroom("bathroom");
return this;
}
}
</pre></div>
<div><b>HouseBuilder.java</b></div>
<div><pre class="brush: java" name="java"> package com.design.pattern.builder;
public class HouseBuilder {
public House buildFurnishedHouse() {
return new FurnishedHouseBuilder().
buildBathRoom().
buildBedroom().
buildDoor().
buildWindow().
buildFurniture().
getHouse();
}
public House buildUnfurnishedHouse() {
return new UnfurnishedHouseBuilder().
buildBathRoom().
buildBedroom().
buildDoor().
buildWindow().
getHouse();
}
}
</pre></div>
<div><b>HouseBuilderDemo.java</b></div>
<div><pre class="brush: java" name="java"> package com.design.pattern.builder;
public class HouseBuilderDemo {
public static void main(String[] args) {
House furnishedHouse=new HouseBuilder().buildFurnishedHouse();
House unfurnishedHouse=new HouseBuilder().buildUnfurnishedHouse();
System.out.println("Furnished House : "+furnishedHouse );
System.out.println("Unfurnished House : "+unfurnishedHouse );
}
}
</pre></div>
</div>
<div><b>Output:</b></div><div><b><br /></b></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-7yhofC79A1Q/YIRjndy06bI/AAAAAAAAhyc/J2hgcaCOK0IWMpsc7eZERXQ_h0Cjl1AogCLcBGAsYHQ/s1035/BuilderDesignPattern-output.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="488" data-original-width="1035" src="https://1.bp.blogspot.com/-7yhofC79A1Q/YIRjndy06bI/AAAAAAAAhyc/J2hgcaCOK0IWMpsc7eZERXQ_h0Cjl1AogCLcBGAsYHQ/s16000/BuilderDesignPattern-output.jpg" /></a></div><br /><b><br /></b></div>
<div class="blogger-post-footer">https://scontent-b-mxp.xx.fbcdn.net/hphotos-xap1/v/t1.0-9/10675541_896261013719814_5601513019470361090_n.jpg?oh=741b05a81becaae8bce36db141948a4a&oe=5531762A</div>Krutik Jayswalhttp://www.blogger.com/profile/16691396948811505379noreply@blogger.com0tag:blogger.com,1999:blog-2571457445842624811.post-428243774591228252021-04-23T01:12:00.001-07:002021-04-24T12:53:54.589-07:00Abstract Factory Design Pattern<p style="text-align: justify;">Abstract factory design pattern is factory of factory design pattern. It is a creational design pattern in which we create multiple factory class and for creating factory object as well there will be main factory class. This is most complicated design pattern among other creational design patterns. Its better to understand factory pattern first as abstract factory is enhanced version of factory pattern. To simplify things, I will say we will be having one super factory class which will be responsible for creating factory object among several factory classes.</p>
<p style="text-align: justify;"><br /></p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-ixs2rNUpC0M/YIG-1uI4kMI/AAAAAAAAhwE/cqhBTvmeTvw9gzvXS4j0OFMedrpp9pbCACLcBGAsYHQ/s1455/abstract%2Bfactory%2Bdesign%2Bpattern.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="630" data-original-width="1455" src="https://1.bp.blogspot.com/-ixs2rNUpC0M/YIG-1uI4kMI/AAAAAAAAhwE/cqhBTvmeTvw9gzvXS4j0OFMedrpp9pbCACLcBGAsYHQ/s16000/abstract%2Bfactory%2Bdesign%2Bpattern.jpg" /></a></div>
<br />
<p style="text-align: justify;"><br /></p>
<p style="text-align: justify;">In abstract factory design pattern , we have multiple factory classes which are responsible for object creation. This factory classes are segregated based on the object categorization. Like in our case we have divided the object based on operating system of mobile device and then created factory classes for same. So there are two factory classes in our case Android Device Factory and Apple Device Factory, both of them are created from Abstract Factory class.so we will be using this abstract factory class only for creating objects.</p>
<p style="text-align: justify;"><br /></p>
<p style="text-align: justify;">Object which we will be creating is a Mobile Device , so the base interface will be MobileDevice using which the concret class will be created for actual mobile devices , In our case we have created devices like Android Device1,Apple Device 1 etc..</p>
<p style="text-align: justify;">Let's cut the theory out and make some practical :)</p>
<p style="text-align: justify;"><br /></p>
<p style="text-align: justify;"><b>MobileDevice.java</b></p>
<p style="text-align: justify;">
<pre class="brush: java" name="java"> package com.design.pattern.abstract_factory;
public interface MobileDevice {
public void printDeviceType();
}
</pre>
</p>
<p style="text-align: justify;"><b>AndroidDevice1.java</b></p>
<p style="text-align: justify;">
<pre class="brush: java" name="java"> package com.design.pattern.abstract_factory;
public class AndroidDevice1 implements MobileDevice {
@Override
public void printDeviceType() {
System.out.println("This is Android Device 1");
}
}
</pre>
</p>
<p style="text-align: justify;"><b>AndroidDevice2.java</b></p>
<p style="text-align: justify;">
<pre class="brush: java" name="java"> package com.design.pattern.abstract_factory;
public class AndroidDevice2 implements MobileDevice {
@Override
public void printDeviceType() {
System.out.println("This is Android Device 2");
}
}
</pre>
</p>
<p style="text-align: justify;"><b>AppleDevice1.java</b></p>
<p style="text-align: justify;">
<pre class="brush: java" name="java"> package com.design.pattern.abstract_factory;
public class AppleDevice1 implements MobileDevice {
@Override
public void printDeviceType() {
System.out.println("This is Apple Device 1");
}
}
</pre>
</p>
<p style="text-align: justify;"><b>AppleDevice2.java</b></p>
<p style="text-align: justify;">
<pre class="brush: java" name="java"> package com.design.pattern.abstract_factory;
public class AppleDevice2 implements MobileDevice {
@Override
public void printDeviceType() {
System.out.println("This is Apple Device 2");
}
}
</pre>
</p>
<p style="text-align: justify;"><b>AbstractFactory.java</b></p>
<p style="text-align: justify;">
<pre class="brush: java" name="java"> package com.design.pattern.abstract_factory;
public abstract class AbstractFactory {
abstract MobileDevice getMobileDevice(String deviceName) ;
}
</pre>
</p>
<p style="text-align: justify;"><b>AndroidDeviceFactory.java</b></p>
<p style="text-align: justify;">
<pre class="brush: java" name="java"> package com.design.pattern.abstract_factory;
public class AndroidDeviceFactory extends AbstractFactory {
@Override
MobileDevice getMobileDevice(String deviceName) {
if(deviceName.equals("AndroidDevice1")) {
return new AndroidDevice1();
}else if(deviceName.equals("AndroidDevice2")) {
return new AndroidDevice2();
}else {
return null;
}
}
}
</pre>
</p>
<p style="text-align: justify;"><b>AppleDeviceFactory.java</b></p>
<p style="text-align: justify;">
<pre class="brush: java" name="java"> package com.design.pattern.abstract_factory;
public class AppleDeviceFactory extends AbstractFactory {
@Override
MobileDevice getMobileDevice(String deviceName) {
if(deviceName.equals("AppleDevice1")) {
return new AppleDevice1();
}else if(deviceName.equals("AppleDevice2")) {
return new AppleDevice2();
}else {
return null;
}
}
}
</pre>
</p>
<p style="text-align: justify;"><b>DeviceFactoryProducer.java</b></p>
<p style="text-align: justify;">
<pre class="brush: java" name="java"> package com.design.pattern.abstract_factory;
public class DeviceFactoryProducer {
public static AbstractFactory getDeviceFactory(boolean needOpenSourceOS) {
if (needOpenSourceOS) {
return new AndroidDeviceFactory();
} else {
return new AppleDeviceFactory();
}
}
}
</pre>
</p>
<p style="text-align: justify;"><b>AbstractFactoryDemo.java</b></p>
<p style="text-align: justify;">
<pre class="brush: java" name="java"> package com.design.pattern.abstract_factory;
public class AbstractFactoryDemo {
public static void main(String[] args) {
AbstractFactory openSourceDeviceFactory=DeviceFactoryProducer.getDeviceFactory(true);
MobileDevice android1=openSourceDeviceFactory.getMobileDevice("AndroidDevice1");
android1.printDeviceType();
MobileDevice android2=openSourceDeviceFactory.getMobileDevice("AndroidDevice1");
android2.printDeviceType();
AbstractFactory closedSourceDeviceFactory=DeviceFactoryProducer.getDeviceFactory(false);
MobileDevice apple1=closedSourceDeviceFactory.getMobileDevice("AppleDevice1");
apple1.printDeviceType();
MobileDevice apple2=closedSourceDeviceFactory.getMobileDevice("AppleDevice2");
apple2.printDeviceType();
}
}
</pre>
</p>
<p style="text-align: justify;"><br /></p><div class="blogger-post-footer">https://scontent-b-mxp.xx.fbcdn.net/hphotos-xap1/v/t1.0-9/10675541_896261013719814_5601513019470361090_n.jpg?oh=741b05a81becaae8bce36db141948a4a&oe=5531762A</div>Krutik Jayswalhttp://www.blogger.com/profile/16691396948811505379noreply@blogger.com0tag:blogger.com,1999:blog-2571457445842624811.post-75143345765196449032021-04-22T03:56:00.008-07:002021-04-24T12:53:54.589-07:00Factory Design Patterns<p style="text-align: justify;">Factory design pattern is creational design pattern , this design pattern is used whenever developer does not need to expose the object creational logic. In factory pattern objects are created using the factory class. This class will be having the object creation part. So when ever the new object is needed of specific type we can create the object using the factory class. Below diagram shows the basic structure of factory pattern.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-nbSGVOcXJ2s/YIFOiFRJWpI/AAAAAAAAhvw/pv-ZHstU1F8A8Ai94RHdKD6Nbah_VHkFgCLcBGAsYHQ/s1455/factory%2Bdesign%2Bpattern.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="433" data-original-width="1455" src="https://1.bp.blogspot.com/-nbSGVOcXJ2s/YIFOiFRJWpI/AAAAAAAAhvw/pv-ZHstU1F8A8Ai94RHdKD6Nbah_VHkFgCLcBGAsYHQ/s16000/factory%2Bdesign%2Bpattern.jpg" /></a></div><br /><p style="text-align: justify;"><br /></p><p style="text-align: justify;">One of the example where we can use this design pattern is in a case some predefined parameters are there for creating object. So what we can do in our case is , we can pass the type of object in getShape() method and based on the type with default attributes we can return the required object.</p><p style="text-align: justify;"><br /></p><p style="text-align: justify;">Let's see some practical example of it.</p><p style="text-align: justify;"><b>Shape Class</b></p><p style="text-align: justify;"></p><pre class="brush: java" name="java">package com.design.pattern.factory;
public interface Shape {
void draw();
}
</pre>
<p></p><p style="text-align: justify;"><b>Circle Class</b></p><p style="text-align: justify;">
</p><pre class="brush: java" name="java">package com.design.pattern.factory;
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Drawing circle...");
}
}
</pre>
<p></p><p style="text-align: justify;"><b>Triangle Class</b></p><p style="text-align: justify;"></p><pre class="brush: java" name="java">package com.design.pattern.factory;
public class Triangle implements Shape {
@Override
public void draw() {
System.out.println("Drawing triangle...");
}
}
</pre>
<p></p><p style="text-align: justify;"><b>Rectangle Class</b></p><p style="text-align: justify;">
</p><pre class="brush: java" name="java">package com.design.pattern.factory;
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Drawing rectangle...");
}
}
</pre>
<p></p><p style="text-align: justify;"><b>ShapeFactory Class</b></p><p style="text-align: justify;">
</p><pre class="brush: java" name="java">package com.design.pattern.factory;
public class ShapeFactory {
public static final String CIRCLE="circle";
public static final String TRIANGLE="triangle";
public static final String RECTANGLE="rectangle";
public Shape getShape(String shapeType) {
if (shapeType == null) {
return null;
}
if (shapeType.equalsIgnoreCase(CIRCLE)) {
return new Circle();
} else if (shapeType.equalsIgnoreCase(RECTANGLE)) {
return new Rectangle();
} else if (shapeType.equalsIgnoreCase(TRIANGLE)) {
return new Triangle();
}
return null;
}
}
</pre>
<p></p><p style="text-align: justify;"><b>FactoryDemo Class</b></p><p style="text-align: justify;">
</p><pre class="brush: java" name="java">package com.design.pattern.factory;
public class FactoryDemo {
public static void main(String[] args) {
ShapeFactory shapeFactory = new ShapeFactory();
Shape shape1 = shapeFactory.getShape(ShapeFactory.CIRCLE);
Shape shape2 = shapeFactory.getShape(ShapeFactory.TRIANGLE);
Shape shape3 = shapeFactory.getShape(ShapeFactory.RECTANGLE);
shape1.draw();
shape2.draw();
shape3.draw();
}
}
</pre>
<p></p><div class="separator" style="clear: both; text-align: center;"><br /></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-YkCwRVUHs3M/YIFX0XnDliI/AAAAAAAAhv8/6CU64z9dTlULFxEd-3TiD5kPYnVBSwR5QCLcBGAsYHQ/s1018/Factory%2BOutput.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="616" data-original-width="1018" src="https://1.bp.blogspot.com/-YkCwRVUHs3M/YIFX0XnDliI/AAAAAAAAhv8/6CU64z9dTlULFxEd-3TiD5kPYnVBSwR5QCLcBGAsYHQ/s16000/Factory%2BOutput.png" /></a></div><br /><p style="text-align: justify;"><br /></p><div class="blogger-post-footer">https://scontent-b-mxp.xx.fbcdn.net/hphotos-xap1/v/t1.0-9/10675541_896261013719814_5601513019470361090_n.jpg?oh=741b05a81becaae8bce36db141948a4a&oe=5531762A</div>Krutik Jayswalhttp://www.blogger.com/profile/16691396948811505379noreply@blogger.com0tag:blogger.com,1999:blog-2571457445842624811.post-35996863145247456742021-04-21T09:58:00.006-07:002021-04-24T12:53:54.589-07:00Prototype Design Pattern<p style="text-align: justify;">Prototype design pattern is creational design pattern. Developers needs to use this design pattern when the object creation is costlier in terms o resources or by some other means. One of the example of costly object creation is that , while creating object we need to make some database calls or may be some webservice calls. In this case we should use prototype design pattern. This pattern is doing nothing special , what it does is it is cashing the new created object and whenever required it will clone this cashed object and will return that copy to the client.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-0m6CWZmdHZ8/YIEgv5CvBCI/AAAAAAAAhvg/my2yY7RwqKYAmIwULgxz0OaixzyRcsPFQCLcBGAsYHQ/s1455/prototype%2Bdesign%2Bpattern.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="433" data-original-width="1455" src="https://1.bp.blogspot.com/-0m6CWZmdHZ8/YIEgv5CvBCI/AAAAAAAAhvg/my2yY7RwqKYAmIwULgxz0OaixzyRcsPFQCLcBGAsYHQ/s16000/prototype%2Bdesign%2Bpattern.jpg" /></a></div><br /><p style="text-align: justify;"><br /></p><p style="text-align: justify;">We will be having one abstract class in which we will be implementing the cloneable interface. The reason behind implementing the cloneable interface is that, that every subsequent class which will be extending this base abstract class will be using this base method implementation from abstract class. In above mentioned class we have the abstract class named as Shape so we will implement clone method in that class.</p><p></p><p style="text-align: justify;">One more things which needs to be done is, we need to create each type of object and cache it in some kind of store like HashMap or HashTable and whenever required we can return the required type of object by cloning the cached copy. Let's see some practical example now.</p><p style="text-align: justify;"><br /></p><p style="text-align: justify;"><b>Abstract Shape Class</b></p><p style="text-align: justify;"> </p><pre class="brush: java" name="java">public abstract class Shape implements Cloneable {
public Object clone() {
Object clone = null;
try {
clone = super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return clone;
}
abstract String displayType();
}</pre><p></p><p style="text-align: justify;"><b>Circle Class</b></p><p style="text-align: justify;"> </p><pre class="brush: java" name="java">package com.design.pattern.prototype;
public class Circle extends Shape {
private String type;
public Circle() {
this.type = "Circle";
}
public String displayType() {
return "This is "+type+" of object";
}
}
</pre><p></p><p style="text-align: justify;"><b>Rectangle Class</b></p><p style="text-align: justify;"> </p><pre class="brush: java" name="java">package com.design.pattern.prototype;
public class Rectangle extends Shape {
private String type;
public Rectangle() {
this.type = "rectangle";
}
public String displayType() {
return "This is "+type+" of object";
}
}
</pre><p></p><p style="text-align: justify;"><b>Triangle Class</b></p><p style="text-align: justify;"> </p><pre class="brush: java" name="java">package com.design.pattern.prototype;
public class Triangle extends Shape{
private String type;
public Triangle() {
this.type = "Triangle";
}
public String displayType() {
return "This is "+type+" of object";
}
}
</pre><p></p><p style="text-align: justify;"><b>ShapeStore Class</b></p><p style="text-align: justify;"> </p><pre class="brush: java" name="java">package com.design.pattern.prototype;
import java.util.HashMap;
import java.util.Map;
public class ShapeStore {
public static Map<string hape=""> cachedObjects=new HashMap<>();
public static void loadObjects() {
cachedObjects.put("circle", new Circle());
cachedObjects.put("triangle", new Triangle());
cachedObjects.put("rectangle", new Rectangle());
}
public static Shape getShape(String shape) {
return (Shape) cachedObjects.get(shape).clone();
}
}
</string></pre><p></p><p style="text-align: justify;"><b>PrototypeDemo Class</b></p><p style="text-align: justify;"> </p><pre class="brush: java" name="java">package com.design.pattern.prototype;
public class PrototypeDemo {
public static void main(String[] args) {
ShapeStore.loadObjects();
Shape circle=ShapeStore.getShape("circle");
Shape triangle=ShapeStore.getShape("triangle");
Shape rectangle=ShapeStore.getShape("rectangle");
System.out.println(circle.displayType());
System.out.println(triangle.displayType());
System.out.println(rectangle.displayType());
}
}
</pre><p></p><p style="text-align: justify;"></p><div class="separator" style="clear: both; text-align: center;"><a href="https://lh3.googleusercontent.com/-3GKnE_pxZYU/YIEt5vX9HVI/AAAAAAAAhvo/3bxZeewfml0bSFnr2UFn2yOVtAiu6rg9ACLcBGAsYHQ/image.png" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="910" data-original-width="981" src="https://lh3.googleusercontent.com/-3GKnE_pxZYU/YIEt5vX9HVI/AAAAAAAAhvo/3bxZeewfml0bSFnr2UFn2yOVtAiu6rg9ACLcBGAsYHQ/s16000/image.png" /></a></div><br /><br /><p></p><div class="blogger-post-footer">https://scontent-b-mxp.xx.fbcdn.net/hphotos-xap1/v/t1.0-9/10675541_896261013719814_5601513019470361090_n.jpg?oh=741b05a81becaae8bce36db141948a4a&oe=5531762A</div>Krutik Jayswalhttp://www.blogger.com/profile/16691396948811505379noreply@blogger.com0tag:blogger.com,1999:blog-2571457445842624811.post-29417952772113952632021-04-20T03:32:00.020-07:002023-02-13T01:37:59.149-08:00Singleton Design Pattern<p style="background-color: white; box-sizing: border-box; color: #525252; font-family: "Source Sans Pro", sans-serif; font-size: 16px; letter-spacing: 0.5px; line-height: 30px; margin: 0px 0px 25px; padding: 0px; word-spacing: 2px;"><span style="text-align: justify;">The name is singleton design pattern it self tells us regarding what exactly this design pattern will do. Using singleton design pattern we can restrict the object or instance creation only to one instance. So using singleton design pattern only one instance/object of a class will get created.</span></p><p style="background-color: white; box-sizing: border-box; color: #525252; font-family: "Source Sans Pro", sans-serif; font-size: 16px; letter-spacing: 0.5px; line-height: 30px; margin: 0px 0px 25px; padding: 0px; text-align: justify; word-spacing: 2px;">Theoretical we will maintain only one instance of a class inside class. A simple singleton class will have variables, methods and constructor as per below diagram.</p><p style="background-color: white; box-sizing: border-box; color: #525252; font-family: "Source Sans Pro", sans-serif; font-size: 16px; letter-spacing: 0.5px; line-height: 30px; margin: 0px 0px 25px; padding: 0px; text-align: justify; word-spacing: 2px;"><br /></p><p style="background-color: white; box-sizing: border-box; color: #525252; font-family: "Source Sans Pro", sans-serif; font-size: 16px; letter-spacing: 0.5px; line-height: 30px; margin: 0px 0px 25px; padding: 0px; text-align: justify; word-spacing: 2px;"></p><div class="separator" style="clear: both; text-align: center;"><a href="https://lh3.googleusercontent.com/-NadHQ32dOhI/YH6tRwKZaoI/AAAAAAAAhto/Js2JcVvCFAE2jN8yDCPT4u5Z5Mp-FMIEQCLcBGAsYHQ/image.png" style="margin-left: 1em; margin-right: 1em;"><img data-original-height="519" data-original-width="446" src="https://lh3.googleusercontent.com/-NadHQ32dOhI/YH6tRwKZaoI/AAAAAAAAhto/Js2JcVvCFAE2jN8yDCPT4u5Z5Mp-FMIEQCLcBGAsYHQ/s16000/image.png" /></a></div><p style="background-color: white; box-sizing: border-box; color: #525252; font-family: "Source Sans Pro", sans-serif; font-size: 16px; letter-spacing: 0.5px; line-height: 30px; margin: 0px 0px 25px; padding: 0px; text-align: justify; word-spacing: 2px;"><br /></p><p style="text-align: justify;">A simple singleton class will have a instance variable which will maintain the single instance of a class, the reason behind private constructor is that it will not allow object creation outside the class and finally the public get instance method to fetch the instance. Now let's see the java example for same.</p><div>
<pre class="brush: java" name="java">
public class SingleTon {
private static SingleTon instance= new SingleTon();
//private allowed object creation only inside the class
private SingleTon() {
}
public static SingleTon getInstance() {
return instance;
}
}</pre></div><div><div style="text-align: justify;"><br /></div>
<div style="text-align: justify;">
<p style="text-align: justify;">
As you can see in the class, the getInstance() method is returning the static instance created while class is getting loaded. private constructor will restrict the object creation only inside the class.So outside class , it will not able possible to instantiate the object and whenever the object is needed it will be possible to retrieve it using the getInstance method.</p><span><a name='more'></a></span><p style="text-align: justify;">Above was a design of the normal singletone class, where the design is goo for single thread environment.The challange will come when there is a question of good design architecture for multithreaded environment.</p><p style="text-align: justify;">When it comes with multithreading for singleton class, most common answer is the define the <i>getInstance() </i>method as synchronized method , further more people might come up with a thought of portion of code as synchronized.The problem of making method it self as synchronized is that, at a time only one thread will be able to access the main portion of singletone class, so by that way its not a good design for multithreaded environment.</p><p style="text-align: justify;">So for solving this we have double check mechanism, where we put 2 if condition.First one will be outside the synchronized block and one more will be there inside synchronize block.The first if condition is needed so that if the object is already created, we can directly return the created object. Second one is needed because if , first thread went inside the synchronized block when the object was not created.At the same time if second thread is passed the first if condition and went inside the synchronized block then we need to check again , if we do not do that then object will get created again.So for resolving this we need 2nd condition as well inside the synchronized block.</p></div></div>
<pre class="brush: java" name="java">
public class SingleTon {
private static SingleTon instance;
//private allowed object creation only inside the class
private SingleTon() {
}
public static SingleTon getInstance() {
if (instance == null) {
synchronized (SingleTon.class) {
if (instance == null) {
instance = new SingleTon();
}
}
}
return instance;
}
}
</pre>
<div class="blogger-post-footer">https://scontent-b-mxp.xx.fbcdn.net/hphotos-xap1/v/t1.0-9/10675541_896261013719814_5601513019470361090_n.jpg?oh=741b05a81becaae8bce36db141948a4a&oe=5531762A</div>Krutik Jayswalhttp://www.blogger.com/profile/16691396948811505379noreply@blogger.com0tag:blogger.com,1999:blog-2571457445842624811.post-26520299437260592312019-07-29T09:03:00.002-07:002020-02-06T22:49:18.866-08:00jBPM:WorkItemHandlers<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
One of the important feature in jBPM is work item handlers. Using work item handlers we can create the custom service task which accepts certain parameter as argument and can have the output after some processing.There are many things which are achieved in jBPM using work item handlers only.Few of the things are making rest/soap calls,Email Task and the bit of complex example will be to have an work item handlers for saving JPA entity.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Let's begin with the steps for creating work item handler.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b>WorkItemDefinition</b></div>
<div style="text-align: justify;">
<b><br /></b></div>
<div style="text-align: justify;">
First we need to define the work item handler.The definition of work item handler contains the name of it, parameter which can be passed in to the work item handler,display name of the handler,icon of the handler and the category to which it will belong.Simple definition of work item handler will look like below.</div>
<div style="text-align: justify;">
<br />
[<br />
"name" : "<b>Email</b>",<br />
"parameters" : [<br />
"From" : new StringDataType(),<br />
"To" : new StringDataType(),<br />
"Subject" : new StringDataType(),<br />
"Body" : new StringDataType()<br />
],<br />
"displayName" : "Email",<br />
"icon" : "defaultemailicon.gif"<br />
]</div>
<div style="text-align: justify;">
<br />
Note : Please keep in the mind the the name which we are using over here will be used in reference in future. for mapping between this definition and the implementation of work item handler.<br />
<br />
One we have defined our work item handler in work item definition file we can see that handler in the BPMN designer as shown in below screenshot.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://lh3.googleusercontent.com/-RhLodlE6Hwg/XT77b-J9dRI/AAAAAAAAecI/OYG-r4jbHtYs1jLcewM4EOl18I84a6qjACLcBGAs/s1600/WorkItemHandler.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="620" data-original-width="1402" src="https://lh3.googleusercontent.com/-RhLodlE6Hwg/XT77b-J9dRI/AAAAAAAAecI/OYG-r4jbHtYs1jLcewM4EOl18I84a6qjACLcBGAs/s1600/WorkItemHandler.png" /></a></div>
<br />
<br />
<br />
<b>Implementation of WorkItemHandler </b><br />
<b><br /></b>
Once the handler has has been defined inside the work item definition we need to write the implementation of work item handler.For implementation we need to implement the existing interface in our new java class.Name of interface is WorkItemHandler. Let's create one WorkItemHandler which will accept 2 numeric argument and we will display sum of it(Just making it simpler).<br />
<br />
<pre class="brush: java" name="java">
import org.kie.api.runtime.process.WorkItem;
import org.kie.api.runtime.process.WorkItemHandler;
import org.kie.api.runtime.process.WorkItemManager;
public class RestWorkItemHandler implements WorkItemHandler{
@Override
public void executeWorkItem(WorkItem workItem, WorkItemManager manager) {
Integer number1=Integer.parseInt(workItem.getParameter("number1").toString());
Integer number2=Integer.parseInt(workItem.getParameter("number2").toString());
System.out.println(number1+number2);
}
@Override
public void abortWorkItem(WorkItem workItem, WorkItemManager manager) {
}
}
</pre>
<br />
<br />
<br />
<b>Mapping between work item definition and workitem handler.</b><br />
Final step is to create mapping between work item handler and the workitem definition.This mapping we are creating inside kie-deployment-descriptor.Below is the code which we need to add inside above mentioned file.Below configuration can also be done using UI of kie-workbench.<br />
<br />
The name which we have defined inside the work item handler will be used in below for mapping purpose.<br />
<pre class="brush: xml" name="xml">
<work-item-handlers>
<work-item-handler>
<resolver>mvel</resolver>
<identifier>new com.myspace.employeeevaluation.wih.RestWorkItemHandler()</identifier>
<parameters/>
<name>Rest</name>
</work-item-handler>
</work-item-handlers>
</pre>
<br />
<br />
<br />
<br />
<br /></div>
<div style="text-align: justify;">
<b><br /></b></div>
<div style="text-align: justify;">
</div>
<div>
<br /></div>
</div>
<div class="blogger-post-footer">https://scontent-b-mxp.xx.fbcdn.net/hphotos-xap1/v/t1.0-9/10675541_896261013719814_5601513019470361090_n.jpg?oh=741b05a81becaae8bce36db141948a4a&oe=5531762A</div>Krutik Jayswalhttp://www.blogger.com/profile/16691396948811505379noreply@blogger.com0tag:blogger.com,1999:blog-2571457445842624811.post-76544044216050230062019-06-24T08:46:00.001-07:002019-07-29T22:33:51.304-07:00Java 8 : Working of streams <div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
When I first heard of a stream, every body was comparing it with the Collection api, So the picture which was there on my mind was that , it is a new kind of data structure introduced in java.But streams are not the data structure.Streams provides methods using which we can perform multiple operations by pipe lining it to produce the desired result.streams are providing results in lazy manner.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Streams is the best feature, java has introduced till now.With the usage of streams so many things in development are easy.But before understanding streams let's see what kind of problem was there in traditional approach.Let's consider below scenario and how does it can be solved using traditional approach and how it can be solved with streams.</div>
<span style="font-size: large;"><u>Problem Statement</u></span><br />
<div style="text-align: justify;">
<span style="font-size: medium;">There is a list,containing an employee object.In the employee class there are certain fields defined.Fields like name,age,salary and designation.This list contains duplicate objects also.Now we need a list of employees whose salary are more than 30,000/- Rs.</span><br />
<span style="font-size: medium;"><br /></span>
<span style="font-size: medium;">Below is how we can solve it using traditional approach.</span></div>
<div style="text-align: justify;">
<br /></div>
<pre class="brush: java" name="java">
List<employee> emplaoyeeList = getEmployeeList();
List<employee> resultList = new ArrayList<>();
for(int i=0;i<emplaoyeelist .size="" emplaoyeelist.get="" getsalary="" i="" if=""> 30000 && !resultList.contains(emplaoyeeList.get(i))) {
resultList.add(emplaoyeeList.get(i));
}
}
</pre>
<br />
Now, let's see the code for solving the same problem using streams.
<br />
<pre class="brush: java" name="java">
List<employee> emplaoyeeList = getEmployeeList();
List<Employee> resultList = emplaoyeeList.stream().
distinct()
.filter(e -> e.getSalary()>30000).
collect(Collectors.toList());
</pre>
<div style="text-align: justify;">
As its visible, the code is much smaller for the same things.There might be certain logical diferrence between the logic for traditional approach.But even the best logic will not be able to bit streams.In case of streams we just need to call certain methods for filtering out the results and that's it.We have seen some basic things on streams ,Now lets see the kind of operations which we can perform on streams.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-size: large;"><u>Intermediate Operations</u></span><br />
<span style="font-size: large;"><u><br /></u></span>
<span style="font-size: medium;">Intermediate operation returns the object of stream type only,The reason is that,by pipe lining the results we can perform multiple operations.</span></div>
<div style="text-align: justify;">
</div>
<div style="font-weight: bold;">
<b><br /></b>
<b>sorted </b></div>
<div>
<br />
sorted method is used for sorting the stream.<br />
Example:<br />
<pre class="brush: java" name="java">
List<string> letters = Arrays.asList("B","A","C");
List<string> result = letters.stream().map(x->x+" : "+x).collect(Collectors.toList());
System.out.println(result);
</pre>
<br />
Output:<br />
<span style="white-space: pre;"> </span>[A, B, C]</div>
<div>
<br /></div>
<div>
<b>map</b></div>
<div>
<br />
map method is used for mapping an object in different one based on predicate passed in to it.<br />
Example:<br />
<pre class="brush: java" name="java">
List<string> letters = Arrays.asList("B","A","C");
List<string> result = letters.stream().map(x->x+" : "+x).collect(Collectors.toList());
System.out.println(result);
</pre>
Output:<br />
<span style="white-space: pre;"> </span>[B : B, A : A, C : C]</div>
<div>
<br /></div>
<div>
<b>filter</b></div>
<div>
<br />
filter method is used for filtering the stream, based on certain parameter.<br />
Example:<br />
<pre class="brush: java" name="java">
List<String> letters = Arrays.asList("B","BigSize","C");
List<String> result = letters.stream().filter(x -> x.length()<2).collect(Collectors.toList());
System.out.println(result);
</pre>
Output:
[B, C]
<b>distinct</b>
Using distinct operation we can remove the duplicate element from the stream.Let's see the example.
Example:
<br />
<pre class="brush: java" name="java">
List<String> mychar = new ArrayList<String>();
mychar.add("A");
mychar.add("B");
mychar.add("C");
mychar.add("A");
mychar.add("F");
System.out.println(mychar.stream().distinct().count());
</pre>
Output:<br />
4
</div>
<div>
<span style="font-size: large; text-align: justify;"><u>Terminal Operations</u></span><br />
<span style="text-align: justify;"><br /></span>
<span style="text-align: justify;">Using terminal operations we can get the resultant type of object.For example list of string.In terminal operation result type will not be of stream.</span><br />
<span style="text-align: justify;"><b><br /></b></span>
<span style="text-align: justify;"><b>collect</b></span><br />
<div style="text-align: justify;">
<br />
After performing the operations on collection, if we want the resultant object as collection in that case we can use the collect.<br />
<div style="text-align: left;">
Example:</div>
<pre class="brush: java" name="java">
List<String> letters = Arrays.asList("B","BigSize","C");
List<String> result = letters.stream().filter(x -> x.length()<2).collect(Collectors.toList());
System.out.println(result);
</pre>
<div style="text-align: left;">
Output:</div>
<div style="text-align: left;">
<span style="white-space: pre;"> </span>[B, C]</div>
</div>
<span style="text-align: justify;"><b><br /></b></span>
<span style="text-align: justify;"><b>forEach</b></span><br />
<span style="text-align: justify;"><br /></span>
<span style="text-align: justify;">This method is used when we want to iterate element of the stream.For printing each element of print.</span><br />
<span style="text-align: justify;">Example:</span><br />
<pre class="brush: java" name="java">
List<String> lettersForEach = Arrays.asList("B","BigSize","C");
lettersForEach.stream().forEach(x->{
System.out.println(x);
});
</pre>
<span style="text-align: justify;"></span><br />
<div style="text-align: justify;">
<span style="white-space: pre;"> </span>});</div>
<div style="text-align: justify;">
Output:</div>
<div style="text-align: justify;">
<div>
<span style="white-space: pre;"> </span>B</div>
<div>
<span style="white-space: pre;"> </span>BigSize</div>
<div>
<span style="white-space: pre;"> </span>C</div>
<div>
<br /></div>
</div>
<span style="text-align: justify;"><b>reduce</b></span><br />
<span style="text-align: justify;"><br /></span>
<span style="text-align: justify;">reduce method is taking BinaryOperator as parameter.This is bit difficult to explain.By looking at the code and its output, people will get more idea on that.So let's take a look over that.</span><br />
<span style="text-align: justify;"><br /></span>
<span style="text-align: justify;">Example:</span><br />
<br />
<pre class="brush: java" name="java">
List<String> reduceChar = new ArrayList<String>();
reduceChar.add("A");
reduceChar.add("B");
reduceChar.add("C");
reduceChar.add("D");
reduceChar.add("F");
Optional<String> reduced = reduceChar.stream().reduce((s1, s2) -> {
System.out.println(s1 +" : "+s2);
return s2;
});
System.out.println(reduced);
</pre>
Output:<br />
<br />
<div style="text-align: justify;">
<span style="white-space: pre;"> </span>A : B</div>
<div style="text-align: justify;">
<span style="white-space: pre;"> </span>B : C</div>
<div style="text-align: justify;">
<span style="white-space: pre;"> </span>C : D</div>
<div style="text-align: justify;">
<span style="white-space: pre;"> </span>D : F</div>
<div style="text-align: justify;">
<span style="white-space: pre;"> </span>Optional[F]</div>
<div style="text-align: justify;">
<b><br /></b>
<b>count</b></div>
<div style="text-align: justify;">
<br />
Using count operation we can count the number of element inside stream.Let's consider an example where we want count of distinct element.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Example:</div>
<pre class="brush: java" name="java">
List<String> countStream = new ArrayList<String>();
countStream.add("A");
countStream.add("B");
countStream.add("C");
countStream.add("A");
countStream.add("F");
System.out.println(countStream.stream().distinct().count());
</pre>
<div style="text-align: justify;">
Output: </div>
<div style="text-align: justify;">
4</div>
<div style="text-align: justify;">
<br /></div>
</div>
</div>
<div class="blogger-post-footer">https://scontent-b-mxp.xx.fbcdn.net/hphotos-xap1/v/t1.0-9/10675541_896261013719814_5601513019470361090_n.jpg?oh=741b05a81becaae8bce36db141948a4a&oe=5531762A</div>Krutik Jayswalhttp://www.blogger.com/profile/16691396948811505379noreply@blogger.com0tag:blogger.com,1999:blog-2571457445842624811.post-21093282822375688052019-06-21T11:43:00.000-07:002020-02-06T22:50:27.161-08:00Java : Internal working of hashmap<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="font-size: large;"><u>Introduction</u></span><br />
<span style="font-size: large;"><br /></span>
The most important question to evaluate any person in java is to ask the architecture of hashmap and how hashmap is internally working in Java.We will begin with the basic understand of hashmap.<br />
<br />
<div style="text-align: left;">
<span style="font-size: large;"><u>
What is HashMap?</u></span></div>
<div style="text-align: left;">
<br /></div>
<div>
HashMap is nothing but the implementation of Map interface in Java. HashMap is introduced in Java in Java version 1.2. HashMap is storing the data in the Key,Value Pair.The HashMap is called as HashMap because it is internally working on a technique called hashing.Another important point to note here is that the key in HashMap obejct is unique.</div>
<div>
<br />
<div style="text-align: left;">
<span style="font-size: large;"><u>
Internal working of hashmap</u></span></div>
</div>
<div>
<br /></div>
<div>
The main data structure internally used by hashmap are array and linked list(as you can see in below image).</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://lh3.googleusercontent.com/-JMl3S94LUFA/XQMxfGu_7_I/AAAAAAAAeFQ/mXE5VJV0JWANJkocvq_KqCVx_Mb1SSm3wCLcBGAs/s1600/Hashmap.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="815" data-original-width="1600" src="https://lh3.googleusercontent.com/-JMl3S94LUFA/XQMxfGu_7_I/AAAAAAAAeFQ/mXE5VJV0JWANJkocvq_KqCVx_Mb1SSm3wCLcBGAs/s1600/Hashmap.png" /></a></div>
<br /></div>
<div>
<br />
Consider that object of hashmap is created using below code.<br />
<br />
<i>Map<Integer, String> hashMap = new HashMap<String,</i><i>Integer,</i><i>>() </i><br />
<i><br /></i>
Now on above object each method written on above image is called.When <b><i>put</i> method </b>will be called using values of the hashmap.<br />
<br />
<ol style="text-align: left;">
<li>Calculate hashvalue for key1.</li>
<li>Based on hashvalue calculate the index.( hashValue & n-1) where n is size of array.</li>
<li>If at the calculated index of array there is no element then it will add the value in the first linked list node.</li>
<li>If value does exist at the calculated index using hash value, it will go to the last linked list node on particular index and will append the value.</li>
</ol>
<div>
Now consider a scenario where the <i><b>get method </b></i>of an object is called.In this case it will follow below things.</div>
<div>
<br /></div>
<br />
<ol>
<li>Calculate hashvalue specified in method arguments of get method.</li>
<li>Based on hashvalue calculate the index.( hashValue & n-1) where n is size of array.</li>
<li>If at the calculated index of array there is only one element then it will return that value</li>
<li>If there are multiple nodes available at the calculated index, it will first compare the hashValue and if it is the same it will compare the key using equals method.</li>
</ol>
<div>
</div>
<br />
<div>
<br /></div>
<div>
<br /></div>
<br />
<div style="text-align: left;">
<span style="font-size: large;"><u>
Design of HashMap Class</u></span></div>
</div>
<div>
<br /></div>
<div>
You can find java file of HashMap.java on below git link.</div>
<div>
<br /></div>
<div>
<a href="https://github.com/openjdk-mirror/jdk7u-jdk/blob/master/src/share/classes/java/util/HashMap.java">https://github.com/openjdk-mirror/jdk7u-jdk/blob/master/src/share/classes/java/util/HashMap.java</a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
Inside the HashMap class, which is inside the java.util package,there is a static class named as Node containing below four fields.</div>
<div>
<br /></div>
<div>
<ol style="text-align: left;">
<li>hash => Hash value of a value calculated using hashing</li>
<li>value=>value of node.</li>
<li>key=>Key of a node</li>
<li>next=>Pointer to the next node.</li>
</ol>
<div>
<div style="text-align: justify;">
Now lets see how it works, First it will do the hashing of key.What exactly hashing does is converting an object in to integer value.This value is calculated using the Hashcode method of object class.Once we have the hash value.We need to add value of hashmap at the index which is calculated using hashing technique.</div>
<div style="text-align: justify;">
Now the problem here is that the hashing value is too long.If we add the value of hashmap at the index of hashvalue the array will become so much larger.So what hashmap does here is that, using the default size of array and bitwise operator it will calculate the index of value in array.</div>
<div style="text-align: justify;">
Once the index value is calculated ,It will create and object of node and it will add that node i linked list.IF the specified index is null the head pointer of that linked list will to this element other wise appended at the last value.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Another point to note in hashmap is about the instance variable.There are many instance variable declared in hashmap class.But the important one are <i>table,threshold </i>and <i>loadfactor. table </i>is array in which all the key,values are getting stored.<i>threshold </i>is a variable whic is usefull in identification whether the array is full or not.If the array becomes full it will double the size of array.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Now if the numbers of keys added are greater than the <i>threshold </i>value than it will expand the map.In the <i>put/putAll </i>method this check has been made.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Default initial capacity of <i>table </i>inside hashmap class it 16.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
</div>
<div>
<br /></div>
<div>
<br /></div>
</div>
</div>
<div class="blogger-post-footer">https://scontent-b-mxp.xx.fbcdn.net/hphotos-xap1/v/t1.0-9/10675541_896261013719814_5601513019470361090_n.jpg?oh=741b05a81becaae8bce36db141948a4a&oe=5531762A</div>Krutik Jayswalhttp://www.blogger.com/profile/16691396948811505379noreply@blogger.com1Pune, Maharashtra, India18.5204303 73.85674369999992518.2795358 73.534020199999929 18.7613248 74.17946719999992tag:blogger.com,1999:blog-2571457445842624811.post-86041693924451449682018-06-20T23:32:00.000-07:002018-06-25T00:13:37.313-07:00Share Form Engine<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
It was always interesting for me, to know that how the form is getting rendered in alfresco share.As a beginner, developer start with customizing share-config-custom.xml where we are defining the forms for workflows, document types, aspects.Configurations for content type,folder type and workflow forms are the major things which is handled by share form engine.But there are other interesting things as well like validation handler,configurations of set(grouping fields) etc..It will be interesting to know, that when we are defining this in share configuration , how alfresco is using it internally.So let's begin.<br />
<br />
<br />
<img src="https://i.pinimg.com/originals/cb/63/00/cb63001dd547467ccaecf1e96a247984.png" />
<br />
<br /></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
There are multiple places from where. form is getting rendered.Few examples will be , Edit properties dialog,Edit Properties Page,Create Document etc..Apart from this, form can be opened by some custom actions as well(by specifying itemid ,itemkind and form id in argument).</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
This all things will call only one webscript which is responsible for rendering form, that is the webscript Form Component.Let's take a look on each file of this webscript.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b>form.get.desc.xml
</b></div>
<div style="text-align: justify;">
As the name says its the webscript descriptor file.Nothing major to describe.<br />
<br />
<b>forms-bootstrap-context.xml</b><br />
This file is defined under ,common-webframework project,It contains the java bean for injecting webscript.Below is code of it.<br />
<pre class="brush: xml" name="xml">
<beans>
<bean class="org.alfresco.web.scripts.forms.FormUIGet" id="webscript.org.alfresco.components.form.form.get" parent="webscript">
<property name="configService" ref="web.config">
</property></bean>
</beans>
</pre>
<br /></div>
<b></b><br />
<a name='more'></a><b>FormUIGet.java</b><br />
<div style="text-align: justify;">
This file contains the code for java file, basically its a code of java baked webscript.It is too long file, So we will just go with some basics of it.Basically what this does is , it will get the form which we have defined inside the share-config-custom.xml or from any other form configuration file and than depending on the parameter which are passed from share UI.It will process the request and will pass it to the free-marker template.If you take a look at generateModel method, it is calling some other methods like getFormConfig(itemId, formId),getVisibleFields(mode, formConfig) etc..So basically ,what it does is, getting the form configuration from xml file and pass it to the freemarker template.
</div>
<pre class="brush: java" name="java">package org.alfresco.web.scripts.forms;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpSession;
import org.alfresco.web.config.forms.ConstraintHandlerDefinition;
import org.alfresco.web.config.forms.ConstraintHandlersConfigElement;
import org.alfresco.web.config.forms.Control;
import org.alfresco.web.config.forms.ControlParam;
import org.alfresco.web.config.forms.DefaultControlsConfigElement;
import org.alfresco.web.config.forms.FormConfigElement;
import org.alfresco.web.config.forms.FormField;
import org.alfresco.web.config.forms.FormSet;
import org.alfresco.web.config.forms.FormsConfigElement;
import org.alfresco.web.config.forms.Mode;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import org.springframework.extensions.config.Config;
import org.springframework.extensions.config.ConfigElement;
import org.springframework.extensions.config.ConfigService;
import org.springframework.extensions.surf.FrameworkUtil;
import org.springframework.extensions.surf.RequestContext;
import org.springframework.extensions.surf.ServletUtil;
import org.springframework.extensions.surf.support.ThreadLocalRequestContext;
import org.springframework.extensions.surf.util.I18NUtil;
import org.springframework.extensions.surf.util.StringBuilderWriter;
import org.springframework.extensions.webscripts.AbstractMessageHelper;
import org.springframework.extensions.webscripts.Cache;
import org.springframework.extensions.webscripts.ConfigModel;
import org.springframework.extensions.webscripts.DeclarativeWebScript;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScript;
import org.springframework.extensions.webscripts.WebScriptException;
import org.springframework.extensions.webscripts.WebScriptRequest;
import org.springframework.extensions.webscripts.connector.Connector;
import org.springframework.extensions.webscripts.connector.ConnectorContext;
import org.springframework.extensions.webscripts.connector.ConnectorService;
import org.springframework.extensions.webscripts.connector.HttpMethod;
import org.springframework.extensions.webscripts.connector.Response;
import org.springframework.extensions.webscripts.json.JSONWriter;
import org.springframework.util.StringUtils;
/**
* Form UI Component web script implementation.
*
* Requests the form definition from the server, combines that with the form
* configuration for the item being requested resulting in the form UI model
* which gets passed to the FreeMarker engine for rendering.
*
* NOTE: The general approach to naming in this class is as follows:
* - processXYZ: Logic
* - discoverXYZ: Searching context for appropriate value
* - generateXYZ: Creating model representations
* - retrieveXYZ: Fetches data from another service
*
* @author Gavin Cornwell
*/
public class FormUIGet extends DeclarativeWebScript
{
private static Log logger = LogFactory.getLog(FormUIGet.class);
protected static final String PROPERTY = "property";
protected static final String ASSOCIATION = "association";
protected static final String PROP_PREFIX = "prop:";
protected static final String FIELD = "field";
protected static final String SET = "set";
protected static final String ASSOC_PREFIX = "assoc:";
protected static final String OLD_DATA_TYPE_PREFIX = "d:";
protected static final String ENDPOINT_ID = "alfresco";
protected static final String ALFRESCO_PROXY = "/proxy/alfresco";
protected static final String CM_NAME_PROP = "prop_cm_name";
protected static final String MSG_DEFAULT_SET_LABEL = "form.default.set.label";
protected static final String MSG_DEFAULT_FORM_ERROR = "form.error";
protected static final String INDENT = " ";
protected static final String DELIMITER = "#alf#";
protected static final String SUBMIT_TYPE_MULTIPART = "multipart";
protected static final String SUBMIT_TYPE_JSON = "json";
protected static final String SUBMIT_TYPE_URL = "urlencoded";
protected static final String ENCTYPE_MULTIPART = "multipart/form-data";
protected static final String ENCTYPE_JSON = "application/json";
protected static final String ENCTYPE_URL = "application/x-www-form-urlencoded";
protected static final String DEFAULT_MODE = "edit";
protected static final String DEFAULT_SUBMIT_TYPE = SUBMIT_TYPE_MULTIPART;
protected static final String DEFAULT_METHOD = "post";
protected static final String DEFAULT_FIELD_TYPE = "text";
protected static final String DEFAULT_CONSTRAINT_EVENT = "blur";
protected static final String CONFIG_FORMS = "forms";
protected static final String PARAM_ITEM_KIND = "itemKind";
protected static final String PARAM_ITEM_ID = "itemId";
protected static final String PARAM_FORM_ID = "formId";
protected static final String PARAM_SUBMIT_TYPE = "submitType";
protected static final String PARAM_SUBMISSION_URL = "submissionUrl";
protected static final String PARAM_JS = "js";
protected static final String PARAM_ERROR_KEY = "err";
protected static final String CONSTRAINT_MANDATORY = "MANDATORY";
protected static final String CONSTRAINT_LIST = "LIST";
protected static final String CONSTRAINT_LENGTH = "LENGTH";
protected static final String CONSTRAINT_NUMBER = "NUMBER";
protected static final String CONSTRAINT_MINMAX = "MINMAX";
protected static final String CONSTRAINT_REGEX = "REGEX";
protected static final String CONSTRAINT_NODE_HANDLER = "Alfresco.forms.validation.nodeName";
protected static final String CONSTRAINT_FILE_NAME_HANDLER = "Alfresco.forms.validation.fileName";
protected static final String CONSTRAINT_MSG_LENGTH = "form.field.constraint.length";
protected static final String CONSTRAINT_MSG_MINMAX = "form.field.constraint.minmax";
protected static final String CONSTRAINT_MSG_NUMBER = "form.field.constraint.number";
protected static final String CONTROL_SELECT_MANY = "/org/alfresco/components/form/controls/selectmany.ftl";
protected static final String CONTROL_SELECT_ONE = "/org/alfresco/components/form/controls/selectone.ftl";
protected static final String CONTROL_PARAM_OPTIONS = "options";
protected static final String CONTROL_PARAM_OPTION_SEPARATOR = "optionSeparator";
protected static final String MODEL_DATA = "data";
protected static final String MODEL_DEFINITION = "definition";
protected static final String MODEL_FIELDS = "fields";
protected static final String MODEL_FORM_DATA = "formData";
protected static final String MODEL_FORCE = "force";
protected static final String MODEL_MESSAGE = "message";
protected static final String MODEL_PROTECTED_FIELD = "protectedField";
protected static final String MODEL_REPEATING = "repeating";
protected static final String MODEL_DEFAULT_VALUE = "defaultValue";
protected static final String MODEL_FORM = "form";
protected static final String MODEL_ERROR = "error";
protected static final String MODEL_NAME = "name";
protected static final String MODEL_MODE = "mode";
protected static final String MODEL_METHOD = "method";
protected static final String MODEL_ENCTYPE = "enctype";
protected static final String MODEL_SUBMISSION_URL = "submissionUrl";
protected static final String MODEL_SHOW_CANCEL_BUTTON = "showCancelButton";
protected static final String MODEL_SHOW_RESET_BUTTON = "showResetButton";
protected static final String MODEL_SHOW_SUBMIT_BUTTON = "showSubmitButton";
protected static final String MODEL_SHOW_CAPTION = "showCaption";
protected static final String MODEL_DESTINATION = "destination";
protected static final String MODEL_REDIRECT = "redirect";
protected static final String MODEL_ARGUMENTS = "arguments";
protected static final String MODEL_STRUCTURE = "structure";
protected static final String MODEL_CONSTRAINTS = "constraints";
protected static final String MODEL_VIEW_TEMPLATE = "viewTemplate";
protected static final String MODEL_EDIT_TEMPLATE = "editTemplate";
protected static final String MODEL_CREATE_TEMPLATE = "createTemplate";
protected static final String MODEL_TYPE = "type";
protected static final String MODEL_LABEL = "label";
protected static final String MODEL_DESCRIPTION = "description";
protected static final String MODEL_MANDATORY = "mandatory";
protected static final String MODEL_DATA_TYPE = "dataType";
protected static final String MODEL_DATA_TYPE_PARAMETERS = "dataTypeParameters";
protected static final String MODEL_DATA_KEY_NAME = "dataKeyName";
protected static final String MODEL_ENDPOINT_TYPE = "endpointType";
protected static final String MODEL_ENDPOINT_MANDATORY = "endpointMandatory";
protected static final String MODEL_ENDPOINT_MANY = "endpointMany";
protected static final String MODEL_ENDPOINT_DIRECTION = "endpointDirection";
protected static final String MODEL_JAVASCRIPT = "javascript";
protected static final String MODEL_CAPABILITIES = "capabilities";
protected static final String MODEL_PARAMETERS = "parameters";
protected static final String MODEL_MAX_LENGTH = "maxLength";
protected static final String MODEL_GROUP = "group";
protected static final String MODEL_INDEX_TOKENISATION_MODE = "indexTokenisationMode";
private static final String TYPE_INT ="int";
private static final String TYPE_LONG ="long";
private static final String TYPE_DOUBLE ="double";
private static final String TYPE_FLOAT ="float";
protected ConfigService configService;
private MessageHelper messageHelper = null;
/**
* Sets the ConfigService instance
*
* @param configService ConfigService
*/
public void setConfigService(ConfigService configService)
{
this.configService = configService;
}
@Override
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status, Cache cache)
{
Map<String, Object> model = null;
String itemKind = getParameter(req, PARAM_ITEM_KIND);
String itemId = getParameter(req, PARAM_ITEM_ID);
if (logger.isDebugEnabled())
{
logger.debug(PARAM_ITEM_KIND + " = " + itemKind);
logger.debug(PARAM_ITEM_ID + " = " + itemId);
}
if (itemKind != null && itemId != null && itemKind.length() > 0 && itemId.length() > 0)
{
model = generateModel(itemKind, itemId, req, status, cache);
}
else
{
// an item kind and id have not been provided so return a model
// with a 'form' entry but set to null, this prevents FreeMarker
// adding a default 'form' taglib object to the model.
model = new HashMap<String, Object>(1);
model.put(MODEL_FORM, null);
}
return model;
}
/**
* Generates the model to send to the FreeMarker engine.
*
* @param itemKind The form itemKind
* @param itemId The form itemId
* @param request The WebScriptRequest
* @param status The response status
* @param cache Cache control
* @return Map
*/
protected Map<String, Object> generateModel(String itemKind, String itemId,
WebScriptRequest request, Status status, Cache cache)
{
Map<String, Object> model = null;
// get mode and optional formId
String modeParam = getParameter(request, MODEL_MODE, DEFAULT_MODE);
String formId = getParameter(request, PARAM_FORM_ID);
Mode mode = Mode.modeFromString(modeParam);
if (logger.isDebugEnabled())
logger.debug("Showing " + mode + " form (id=" + formId + ") for item: [" + itemKind + "]" + itemId);
// get the form configuration and list of fields that are visible (if any)
FormConfigElement formConfig = getFormConfig(itemId, formId);
List<String> visibleFields = getVisibleFields(mode, formConfig);
// get the form definition from the form service
Response formSvcResponse = retrieveFormDefinition(itemKind, itemId, visibleFields, formConfig);
if (formSvcResponse.getStatus().getCode() == Status.STATUS_OK)
{
model = generateFormModel(request, mode, formSvcResponse, formConfig);
}
else if (formSvcResponse.getStatus().getCode() == Status.STATUS_UNAUTHORIZED)
{
// set status to 401 and return null model
status.setCode(Status.STATUS_UNAUTHORIZED);
status.setRedirect(true);
}
else
{
String errorKey = getParameter(request, PARAM_ERROR_KEY);
model = generateErrorModel(formSvcResponse, errorKey);
}
return model;
}
/**
* Returns the named parameter.
*
* @param req The WebScriptRequest
* @param name The name of the parameter to find
* @return The value of the parameter or null if not found
*/
protected String getParameter(WebScriptRequest req, String name)
{
return getParameter(req, name, null);
}
/**
* Returns the named parameter, returning the given default
* value if the parameter can not be found.
*
* @param req The WebScriptRequest
* @param name The name of the parameter to find
* @param defaultValue The default value
* @return The value of the parameter or the default value if the
* parameter is not found
*/
protected String getParameter(WebScriptRequest req, String name, String defaultValue)
{
// get the value from the webscript parameters, this should include all context
// properties as well as all the mapped query string parameters
String value = req.getParameter(name);
// if the value is still null or empty use default value, if one
if ((value == null || value.length() == 0) && defaultValue != null)
{
value = defaultValue;
}
if (logger.isDebugEnabled())
logger.debug("Returning \"" + value + "\" from getParameter for \"" + name + "\"");
return value;
}
/**
* Returns the form configuration for the given item id and optional form id.
*
* @param itemId The form itemId
* @param formId The id of the form to lookup
* @return The FormConfigElement object or null if no configuration is found
*/
protected FormConfigElement getFormConfig(String itemId, String formId)
{
FormConfigElement formConfig = null;
FormsConfigElement formsConfig = null;
RequestContext requestContext = ThreadLocalRequestContext.getRequestContext();
ConfigModel extendedTemplateConfigModel = requestContext.getExtendedTemplateConfigModel(null);
if(extendedTemplateConfigModel != null) {
@SuppressWarnings("unchecked")
Map<String, ConfigElement> configs = (Map<String, ConfigElement>) extendedTemplateConfigModel.getScoped().get(itemId);
formsConfig = (FormsConfigElement) configs.get(CONFIG_FORMS);
}
if(formsConfig == null)
{
Config configResult = this.configService.getConfig(itemId);
formsConfig = (FormsConfigElement)configResult.getConfigElement(CONFIG_FORMS);
}
if (formsConfig != null)
{
// Extract the form we are looking for
if (formsConfig != null)
{
// try and retrieve the specified form
if (formId != null && formId.length() > 0)
{
formConfig = formsConfig.getForm(formId);
}
// fall back to the default form
if (formConfig == null)
{
formConfig = formsConfig.getDefaultForm();
}
}
}
else if (logger.isWarnEnabled())
{
logger.warn("Could not lookup form configuration as configService has not been set");
}
return formConfig;
}
/**
* Returns the list of visible field names for the given mode.
*
* @param mode The form mode
* @param formConfig The form configuration
* @return List of field names configured to be visible
*/
protected List<String> getVisibleFields(Mode mode, FormConfigElement formConfig)
{
List<String> visibleFields = null;
if (formConfig != null)
{
// get visible fields for the current mode
switch (mode)
{
case VIEW:
visibleFields = formConfig.getVisibleViewFieldNamesAsList();
break;
case EDIT:
visibleFields = formConfig.getVisibleEditFieldNamesAsList();
break;
case CREATE:
visibleFields = formConfig.getVisibleCreateFieldNamesAsList();
break;
}
}
if (logger.isDebugEnabled())
logger.debug("Fields configured to be visible for " + mode + " mode = " + visibleFields);
return visibleFields;
}
/**
* Returns the list of visible field names for the given set.
*
* @param context The context
* @param setConfig Set configuration
* @return List of field names configured to be visible for the set
*/
protected List<String> getVisibleFieldsInSet(ModelContext context, FormSet setConfig)
{
List<String> visibleFields = null;
Mode mode = context.getMode();
if (setConfig != null)
{
switch (mode)
{
case VIEW:
visibleFields = context.getFormConfig().getVisibleViewFieldNamesForSetAsList(
setConfig.getSetId());
break;
case EDIT:
visibleFields = context.getFormConfig().getVisibleEditFieldNamesForSetAsList(
setConfig.getSetId());
break;
case CREATE:
visibleFields = context.getFormConfig().getVisibleCreateFieldNamesForSetAsList(
setConfig.getSetId());
break;
}
if (logger.isDebugEnabled())
logger.debug("Fields configured to be visible for set \"" + setConfig.getSetId() + "\" = " + visibleFields);
}
return visibleFields;
}
/**
* Retrieves the form definition from the repository FormService for the
* given item.
*
* @param itemKind The form item kind
* @param itemId The form item id
* @param visibleFields The list of field names to return or null
* to return all fields
* @param formConfig The form configuration
* @return Response object from the remote call
*/
protected Response retrieveFormDefinition(String itemKind, String itemId,
List<String> visibleFields, FormConfigElement formConfig)
{
Response response = null;
try
{
// setup the connection
ConnectorService connService = FrameworkUtil.getConnectorService();
RequestContext requestContext = ThreadLocalRequestContext.getRequestContext();
String currentUserId = requestContext.getUserId();
HttpSession currentSession = ServletUtil.getSession(true);
Connector connector = connService.getConnector(ENDPOINT_ID, currentUserId, currentSession);
ConnectorContext context = new ConnectorContext(HttpMethod.POST, null, buildDefaultHeaders());
context.setContentType("application/json");
// call the form service
response = connector.call("/api/formdefinitions", context, generateFormDefPostBody(itemKind,
itemId, visibleFields, formConfig));
if (logger.isDebugEnabled())
logger.debug("Response status: " + response.getStatus().getCode());
}
catch (Exception e)
{
if (logger.isErrorEnabled())
logger.error("Failed to get form definition: ", e);
}
return response;
}
/**
* Helper to build a map of the default headers for script requests - we send over
* the current users locale so it can be respected by any appropriate REST APIs.
*
* @return map of headers
*/
private static Map<String, String> buildDefaultHeaders()
{
Map<String, String> headers = new HashMap<String, String>(1, 1.0f);
headers.put("Accept-Language", I18NUtil.getLocale().toString().replace('_', '-'));
return headers;
}
/**
* Retrieves a localized message string.
*
* @param messageKey The message key to lookup
* @param args Optional replacement arguments
* @return The localized string
*/
protected String retrieveMessage(String messageKey, final Object... args)
{
if (this.messageHelper == null)
{
this.messageHelper = new MessageHelper(this);
}
return this.messageHelper.get(messageKey, args);
}
/**
* Generates the POST body to send to the FormService.
*
* @param itemKind The form item kind
* @param itemId The form item id
* @param visibleFields The list of field names to return or null
* to return all fields
* @param formConfig The form configuration
* @return ByteArrayInputStream representing the POST body
* @throws IOException
*/
protected ByteArrayInputStream generateFormDefPostBody(String itemKind, String itemId,
List<String> visibleFields, FormConfigElement formConfig) throws IOException
{
StringBuilderWriter buf = new StringBuilderWriter(512);
JSONWriter writer = new JSONWriter(buf);
writer.startObject();
writer.writeValue(PARAM_ITEM_KIND, itemKind);
writer.writeValue(PARAM_ITEM_ID, itemId.replace(":/", ""));
List<String> forcedFields = null;
if (visibleFields != null && visibleFields.size() > 0)
{
// list the requested fields
writer.startValue(MODEL_FIELDS);
writer.startArray();
forcedFields = new ArrayList<String>(visibleFields.size());
for (String fieldId : visibleFields)
{
// write out the fieldId
writer.writeValue(fieldId);
// determine which fields need to be forced
if (formConfig.isFieldForced(fieldId))
{
forcedFields.add(fieldId);
}
}
// close the fields array
writer.endArray();
}
// list the forced fields, if present
if (forcedFields != null && forcedFields.size() > 0)
{
writer.startValue(MODEL_FORCE);
writer.startArray();
for (String fieldId : forcedFields)
{
writer.writeValue(fieldId);
}
writer.endArray();
}
// end the JSON object
writer.endObject();
if (logger.isDebugEnabled())
logger.debug("Generated JSON POST body: " + buf.toString());
// return the JSON body as a stream
return new ByteArrayInputStream(buf.toString().getBytes());
}
/**
* Generates the "form" model passed to the FreeMarker engine.
*
* @param request The WebScriptRequest
* @param mode The mode of the form
* @param formSvcResponse Response representing the form definition
* @param formConfig The form configuration
* @return Map representing the "form" model
*/
protected Map<String, Object> generateFormModel(WebScriptRequest request, Mode mode,
Response formSvcResponse, FormConfigElement formConfig)
{
try
{
String jsonResponse = formSvcResponse.getResponse();
if (logger.isDebugEnabled())
logger.debug("form definition JSON = \n" + jsonResponse);
// create JSON representation of form defintion from response
JSONObject formDefinition = new JSONObject(new JSONTokener(jsonResponse));
// create model to return
Map<String, Object> model = new HashMap<String, Object>(1);
model.put(MODEL_FORM, generateFormUIModel(new ModelContext(request, mode, formDefinition, formConfig)));
return model;
}
catch (JSONException je)
{
if (logger.isErrorEnabled())
logger.error(je);
return null;
}
}
/**
* Generates the model that will be processed by the FreeMarker engine
* and thus render the form UI.
*
* @param context The context
* @return Map representing the form UI model
*/
protected Map<String, Object> generateFormUIModel(ModelContext context)
{
// generate the form UI model and add to the context
Map<String, Object> formUIModel = new HashMap<String, Object>(8);
context.setFormUIModel(formUIModel);
// populate the model
formUIModel.put(MODEL_MODE, context.getMode().toString());
formUIModel.put(MODEL_METHOD, getParameter(context.getRequest(), MODEL_METHOD, DEFAULT_METHOD));
formUIModel.put(MODEL_ENCTYPE, discoverEncodingFormat(context));
formUIModel.put(MODEL_SUBMISSION_URL, discoverSubmissionUrl(context));
formUIModel.put(MODEL_ARGUMENTS, discoverArguments(context));
formUIModel.put(MODEL_DATA, discoverData(context));
formUIModel.put(MODEL_SHOW_CANCEL_BUTTON, discoverBooleanParam(context, MODEL_SHOW_CANCEL_BUTTON));
formUIModel.put(MODEL_SHOW_RESET_BUTTON, discoverBooleanParam(context, MODEL_SHOW_RESET_BUTTON));
formUIModel.put(MODEL_SHOW_SUBMIT_BUTTON, discoverBooleanParam(context, MODEL_SHOW_SUBMIT_BUTTON, true));
String destination = getParameter(context.getRequest(), MODEL_DESTINATION);
if (destination != null && destination.length() > 0)
{
formUIModel.put(MODEL_DESTINATION, destination);
}
String redirect = getParameter(context.getRequest(), MODEL_REDIRECT);
if (redirect != null && redirect.length() > 0)
{
formUIModel.put(MODEL_REDIRECT, redirect);
}
// process the capabilities
processCapabilities(context, formUIModel);
// process the optional templates
processTemplates(context, formUIModel);
// process the fields to generate the 'fields', 'structure' and 'constraints'
// properties of the model
processFields(context, formUIModel);
// detect 'showCaption' after 'constraints' were generated
formUIModel.put(MODEL_SHOW_CAPTION, discoverBooleanParam(context, MODEL_SHOW_CAPTION, getDefaultShowCaption(context)));
// dump the model for debugging
dumpFormUIModel(formUIModel);
return formUIModel;
}
/**
* Returns default showCaption flag
*
* @param context The context
* @return Default showCaption flag
*/
private boolean getDefaultShowCaption(ModelContext context)
{
if (context.getMode() == Mode.VIEW)
{
return false;
}
for (Constraint constraint : context.getConstraints())
{
if (CONSTRAINT_MANDATORY.equals(constraint.getId()))
{
return true;
}
}
return false;
}
/**
* Determines the "enctype" that should be used for the form.
*
* @param context The context
* @return The enctype the form should use
*/
protected String discoverEncodingFormat(ModelContext context)
{
String submitType = getParameter(context.getRequest(), PARAM_SUBMIT_TYPE, DEFAULT_SUBMIT_TYPE);
String enctype = null;
if (SUBMIT_TYPE_MULTIPART.equals(submitType))
{
enctype = ENCTYPE_MULTIPART;
}
else if (SUBMIT_TYPE_JSON.equals(submitType))
{
enctype = ENCTYPE_JSON;
}
else if (SUBMIT_TYPE_URL.equals(submitType))
{
enctype = ENCTYPE_URL;
}
else
{
enctype = ENCTYPE_MULTIPART;
}
return enctype;
}
/**
* Determines the "submissionUrl" that should be used for the form.
*
* @param context The context
* @return The submissionUrl the form should use
*/
protected String discoverSubmissionUrl(ModelContext context)
{
String submissionUrl = null;
if (context.getFormConfig() != null && context.getFormConfig().getSubmissionURL() != null)
{
submissionUrl = context.getFormConfig().getSubmissionURL();
}
else
{
String defaultSubmissionUrl = null;
try
{
// get the submission url from the form definition
JSONObject data = context.getFormDefinition().getJSONObject(MODEL_DATA);
defaultSubmissionUrl = data.getString(MODEL_SUBMISSION_URL);
}
catch (JSONException je)
{
// just use the default submission url defined above
throw new WebScriptException("Failed to find default submission URL", je);
}
// if a submission url has been provided use that otherwise use the default
submissionUrl = getParameter(context.getRequest(), PARAM_SUBMISSION_URL, defaultSubmissionUrl);
}
// build the full submission url
submissionUrl = getProxyPath(context) + submissionUrl;
return submissionUrl;
}
/**
* Returns the base path to the proxy to use
*
* @param context Contains the request and context path
* @return The base path to the proxy to use
*/
protected String getProxyPath(ModelContext context)
{
return context.getRequest().getContextPath() + ALFRESCO_PROXY;
}
/**
* Determines the "arguments" that should be used for the form.
*
* @param context The context
* @return The arguments the form should use
*/
protected Map<String, String> discoverArguments(ModelContext context)
{
Map<String, String> arguments = new HashMap<String, String>(3);
arguments.put(PARAM_ITEM_KIND, getParameter(context.getRequest(), PARAM_ITEM_KIND));
arguments.put(PARAM_ITEM_ID, getParameter(context.getRequest(), PARAM_ITEM_ID));
arguments.put(PARAM_FORM_ID, getParameter(context.getRequest(), PARAM_FORM_ID));
return arguments;
}
/**
* Determines the "data" that should be used for the form.
*
* @param context The context
* @return The data the form should use
*/
protected Map<String, Object> discoverData(ModelContext context)
{
Map<String, Object> dataModel = null;
try
{
// get the formData section of the form definition
JSONObject data = context.getFormDefinition().getJSONObject(MODEL_DATA);
JSONObject formData = data.getJSONObject(MODEL_FORM_DATA);
// copy formData into map
JSONArray names = formData.names();
if (names != null)
{
dataModel = new HashMap<String, Object>(names.length());
for (int x = 0; x < names.length(); x++)
{
String key = names.getString(x);
dataModel.put(key, formData.get(key));
}
}
else
{
dataModel = Collections.emptyMap();
}
}
catch (JSONException je)
{
throw new WebScriptException("Failed to find form data", je);
}
return dataModel;
}
/**
* Returns the value of the given boolean parameter.
*
* @param context The context
* @param name The name of the parameter
* @return The value of parameter, false is returned if
* the parameter is not found
*/
protected boolean discoverBooleanParam(ModelContext context, String name)
{
return discoverBooleanParam(context, name, false);
}
/**
* Returns the value of the given boolean parameter.
*
* @param context The context
* @param name The name of the parameter
* @param defaultValue The default value to use if the parameter
* is not found
* @return The value of parameter, defaultValue is returned if
* the parameter is not found
*/
protected boolean discoverBooleanParam(ModelContext context, String name, boolean defaultValue)
{
String value = getParameter(context.getRequest(), name, Boolean.toString(defaultValue));
return ("true".equals(value)) ? true : false;
}
/**
* Returns the field definition for the given field name.
*
* @param context The context
* @param fieldName The name of the field to get the definition for
* @return JSONObject representing the field definition
*/
protected JSONObject discoverFieldDefinition(ModelContext context, String fieldName)
{
JSONObject fieldDefinition = null;
JSONObject propertyDefinition = context.getPropertyDefinitions().get(fieldName);
JSONObject associationDefinition = context.getAssociationDefinitions().get(fieldName);
if (propertyDefinition == null && associationDefinition == null)
{
// if a field definition has not been found yet check for prop: and assoc: prefixes
if (fieldName.indexOf(PROP_PREFIX) != -1)
{
propertyDefinition = context.getPropertyDefinitions().get(
fieldName.substring(PROP_PREFIX.length()));
}
else if (fieldName.indexOf(ASSOC_PREFIX) != -1)
{
associationDefinition = context.getAssociationDefinitions().get(
fieldName.substring(ASSOC_PREFIX.length()));
}
}
// determine if field was a property or association
if (propertyDefinition != null)
{
fieldDefinition = propertyDefinition;
}
else if (associationDefinition != null)
{
fieldDefinition = associationDefinition;
}
return fieldDefinition;
}
/**
* Determines the label to use for the given set configuration.
*
* @param setConfig Set configuration
* @return The label of the set.
*/
protected String discoverSetLabel(FormSet setConfig)
{
String label = null;
if (setConfig.getLabelId() != null)
{
label = retrieveMessage(setConfig.getLabelId());
}
else if (setConfig.getLabel() != null)
{
label = setConfig.getLabel();
}
else
{
// if there is no label specified in the config,
// use the label from the properties file otherwise
// use the set id
if ("".equals(setConfig.getSetId()))
{
label = retrieveMessage(MSG_DEFAULT_SET_LABEL);
}
else
{
label = setConfig.getSetId();
}
}
if (logger.isDebugEnabled())
logger.debug("Returning label for set: " + label);
return label;
}
/**
* Determines the set membership hierarchy.
*
* @param context The context
* @return Map of field name lists representing the set hierarchy
*/
protected Map<String, List<String>> discoverSetMembership(ModelContext context)
{
Map<String, List<String>> setMemberships = new HashMap<String, List<String>>(4);
try
{
// get list of fields from form definition
JSONObject data = context.getFormDefinition().getJSONObject(MODEL_DATA);
JSONObject definition = data.getJSONObject(MODEL_DEFINITION);
JSONArray fieldsFromServer = definition.getJSONArray(MODEL_FIELDS);
// iterate around fields to determine what set they belong to
for (int x = 0; x < fieldsFromServer.length(); x++)
{
JSONObject fieldDefinition = fieldsFromServer.getJSONObject(x);
String fieldName = fieldDefinition.getString(MODEL_NAME);
// determine if this field should even be shown
if (context.getFormConfig().isFieldHidden(fieldName, context.getMode()) == false)
{
// if its visible determine its set membership
String set = "";
if (fieldDefinition.has(MODEL_GROUP))
{
set = fieldDefinition.getString(MODEL_GROUP);
}
FormField fieldConfig = context.getFormConfig().getFields().get(fieldName);
if (fieldConfig != null && fieldConfig.getSet().equals("") == false)
{
set = fieldConfig.getSet();
}
// get the array for the set and add the field to it
List<String> fieldsForSet = setMemberships.get(set);
if (fieldsForSet == null)
{
// setup array for the set
fieldsForSet = new ArrayList<String>(4);
fieldsForSet.add(fieldName);
setMemberships.put(set, fieldsForSet);
}
else
{
fieldsForSet.add(fieldName);
}
}
else if (logger.isDebugEnabled())
{
logger.debug("Ignoring \"" + fieldName + "\" as it is configured to be hidden");
}
}
}
catch (JSONException je)
{
// log the error and return the empty set
if (logger.isErrorEnabled())
logger.error("Failed to discover set membership", je);
}
if (logger.isDebugEnabled())
logger.debug("Set membership = " + setMemberships);
return setMemberships;
}
/**
* Processes the "js" parameter, if present.
*
* @param context The context
* @param formUIModel The form UI model
*/
protected void processCapabilities(ModelContext context, Map<String, Object> formUIModel)
{
String jsEnabled = getParameter(context.getRequest(), PARAM_JS);
if (jsEnabled != null && ("off".equalsIgnoreCase(jsEnabled) ||
"false".equalsIgnoreCase(jsEnabled) || "disabled".equalsIgnoreCase(jsEnabled)))
{
Map<String, Object> capabilities = new HashMap<String, Object>(1);
capabilities.put(MODEL_JAVASCRIPT, false);
formUIModel.put(MODEL_CAPABILITIES, capabilities);
if (logger.isDebugEnabled())
logger.debug("JavaScript disabled flag detected, added form capabilties: " + capabilities);
}
}
/**
* Processes the optional custom templates configuration.
*
* @param context The context
* @param formUIModel The form UI model
*/
protected void processTemplates(ModelContext context, Map<String, Object> formUIModel)
{
FormConfigElement formConfig = context.getFormConfig();
if (formConfig != null && formConfig.getViewTemplate() != null)
{
formUIModel.put(MODEL_VIEW_TEMPLATE, formConfig.getViewTemplate());
if (logger.isDebugEnabled())
logger.debug("Set viewTemplate to \"" + formConfig.getViewTemplate() + "\"");
}
if (formConfig != null && formConfig.getEditTemplate() != null)
{
formUIModel.put(MODEL_EDIT_TEMPLATE, formConfig.getEditTemplate());
if (logger.isDebugEnabled())
logger.debug("Set editTemplate to \"" + formConfig.getEditTemplate() + "\"");
}
if (formConfig != null && formConfig.getCreateTemplate() != null)
{
formUIModel.put(MODEL_CREATE_TEMPLATE, formConfig.getCreateTemplate());
if (logger.isDebugEnabled())
logger.debug("Set createTemplate to \"" + formConfig.getCreateTemplate() + "\"");
}
}
/**
* Processes the "fields" section of the model.
*
* @param context The context
* @param formUIModel The form UI model
*/
protected void processFields(ModelContext context, Map<String, Object> formUIModel)
{
List<String> visibleFields = getVisibleFields(context.getMode(), context.getFormConfig());
if (context.getFormConfig() != null && visibleFields != null && visibleFields.size() > 0)
{
processVisibleFields(context);
}
else
{
processServerFields(context);
}
formUIModel.put(MODEL_FIELDS, context.getFields());
formUIModel.put(MODEL_STRUCTURE, context.getStructure());
formUIModel.put(MODEL_CONSTRAINTS, context.getConstraints());
}
/**
* Processes the fields configured to be visible for the form.
*
* @param context The context
*/
protected void processVisibleFields(ModelContext context)
{
// iterate over the root sets and generate a model for each one
for (FormSet setConfig : context.getFormConfig().getRootSetsAsList())
{
Set set = generateSetModelUsingVisibleFields(context, setConfig);
// if the set got created (as it contained fields or other sets)
// add it to the structure list in the model context
if (set != null)
{
context.getStructure().add(set);
}
}
}
/**
* Processes the fields returned from the server (the form definition), this
* method is called when there are no visible fields configured.
*
* @param context The context
*/
protected void processServerFields(ModelContext context)
{
if (context.getFormConfig() != null)
{
// discover the set membership of the fields using the form definition
Map<String, List<String>> setMembership = discoverSetMembership(context);
// get root sets from config and build set structure using config and lists built above
for (FormSet setConfig : context.getFormConfig().getRootSetsAsList())
{
Set set = generateSetModelUsingServerFields(context, setConfig, setMembership);
// if the set got created (as it contained fields or other sets)
// add it to the structure list in the model context
if (set != null)
{
context.getStructure().add(set);
}
}
}
else
{
// as there is no config at all generate a default set that contains
// all the fields returned in the form definition
Set set = generateDefaultSetModelUsingServerFields(context);
context.getStructure().add(set);
}
}
/**
* Generates the model for the given set, this method also recursively generates any
* child sets the given set has. The contents of the sets are purely driven by the
* configured visible fields.
*
* @param context The context
* @param setConfig The set configuration
* @return The set model
*/
protected Set generateSetModelUsingVisibleFields(ModelContext context, FormSet setConfig)
{
Set set = null;
List<String> fieldsInSet = getVisibleFieldsInSet(context, setConfig);
// if there is something to show in the set create the set object
if ((fieldsInSet != null && fieldsInSet.size() > 0) || setConfig.getChildrenAsList().size() > 0)
{
set = generateSetModel(context, setConfig, fieldsInSet);
// recursively setup child sets
for (FormSet childSetConfig : setConfig.getChildrenAsList())
{
Set childSet = generateSetModelUsingVisibleFields(context, childSetConfig);
set.addChild(childSet);
}
}
else if (logger.isDebugEnabled())
{
logger.debug("Ignoring set \"" + setConfig.getSetId() + "\" as it does not have any fields or child sets");
}
return set;
}
/**
* Generates the model for the given set, this method also recursively generates any
* child sets the given set has. The contents of the sets are the result of combining
* the form configuration and form definition.
*
* @param context The context
* @param setConfig Set configuration
* @param setMembership The set hierarchy
* @return The set model
*/
protected Set generateSetModelUsingServerFields(ModelContext context, FormSet setConfig,
Map<String, List<String>> setMembership)
{
Set set = null;
List<String> fieldsInSet = setMembership.get(setConfig.getSetId());
// if there is something to show in the set create the set object
if ((fieldsInSet != null && fieldsInSet.size() > 0) || setConfig.getChildrenAsList().size() > 0)
{
set = generateSetModel(context, setConfig, fieldsInSet);
// recursively setup child sets
for (FormSet childSetConfig : setConfig.getChildrenAsList())
{
Set childSet = generateSetModelUsingServerFields(context, childSetConfig, setMembership);
set.addChild(childSet);
}
}
else if (logger.isDebugEnabled())
{
logger.debug("Ignoring set \"" + setConfig.getSetId() + "\" as it does not have any fields or child sets");
}
return set;
}
/**
* Generates the model for the given set and it's fields. This method does NOT
* recurse through any child sets.
*
* @param context The context
* @param setConfig The set configuration
* @param fields List of field in the set
* @return The set model
*/
protected Set generateSetModel(ModelContext context, FormSet setConfig, List<String> fields)
{
// create the set from the configuration
Set set = new Set(setConfig);
// create and all the fields to the set
for (String fieldName : fields)
{
FormField fieldConfig = context.getFormConfig().getFields().get(fieldName);
// attempt to generate a field
Field field = generateFieldModel(context, fieldName, fieldConfig);
// if a field was created add it to the map of fields in the model context
// and add a pointer to the field to the set's list of children
if (field != null)
{
set.addChild(new FieldPointer(field.getId()));
context.getFields().put(field.getId(), field);
}
}
return set;
}
/**
* Generates the model for the default set, this will contain all the fields
* returned from the server.
*
* @param context The context
* @return The set model
*/
protected Set generateDefaultSetModelUsingServerFields(ModelContext context)
{
if (logger.isDebugEnabled())
logger.debug("No configuration was found therefore showing all fields in the default set...");
// setup the default set object
Set set = new Set("", retrieveMessage(MSG_DEFAULT_SET_LABEL));
try
{
// add all the fields from the server to the default set
JSONObject data = context.getFormDefinition().getJSONObject(MODEL_DATA);
JSONObject definition = data.getJSONObject(MODEL_DEFINITION);
JSONArray fieldsFromServer = definition.getJSONArray(MODEL_FIELDS);
for (int x = 0; x < fieldsFromServer.length(); x++)
{
String fieldName = fieldsFromServer.getJSONObject(x).getString(MODEL_NAME);
// attempt to generate a field
Field field = generateFieldModel(context, fieldName, null);
// if a field was created add it to the map of fields in the model context
// and add a pointer to the field to the set's list of children
if (field != null)
{
set.addChild(new FieldPointer(field.getId()));
context.getFields().put(field.getId(), field);
}
}
}
catch (JSONException je)
{
// log the error and return the empty set
if (logger.isErrorEnabled())
logger.error("Failed to generate default set from server fields", je);
}
return set;
}
/**
* Generates the model for the given field. The form definition from the form service
* and the given form configuration are combined to give the field model to send to
* the template for rendering.
*
* @param context The context
* @param fieldName The name of the field to be generated
* @param fieldConfig The configuration for the field
* @return A field model
*/
protected Field generateFieldModel(ModelContext context, String fieldName, FormField fieldConfig)
{
if (logger.isDebugEnabled())
logger.debug("Generating model for field \"" + fieldName + "\"");
Field field = null;
try
{
// make sure the field is not ambiguous
if (isFieldAmbiguous(context, fieldName))
{
field = generateTransientFieldModel(fieldName, "/org/alfresco/components/form/controls/ambiguous.ftl");
}
else
{
JSONObject fieldDefinition = discoverFieldDefinition(context, fieldName);
if (fieldDefinition != null)
{
// create the initial field model
field = new Field();
// populate the model with the appropriate data
processFieldIdentification(context, field, fieldDefinition, fieldConfig);
processFieldState(context, field, fieldDefinition, fieldConfig);
processFieldText(context, field, fieldDefinition, fieldConfig);
processFieldData(context, field, fieldDefinition, fieldConfig);
processFieldControl(context, field, fieldDefinition, fieldConfig);
processFieldConstraints(context, field, fieldDefinition, fieldConfig);
processFieldContent(context, field, fieldDefinition, fieldConfig);
}
else
{
// the field does not have a definition but may be a 'transient' field
field = generateTransientFieldModel(context, fieldName, fieldDefinition, fieldConfig);
if (field == null && logger.isDebugEnabled())
logger.debug("Ignoring field \"" + fieldName +
"\" as neither a field definition or sufficient configuration could be located");
}
}
}
catch (JSONException je)
{
if (logger.isErrorEnabled())
logger.error("Failed to generate field model for \"" + fieldName + "\"", je);
field = null;
}
return field;
}
/**
* Determines whether the given field is ambiguous (a property and association
* have the same name).
*
* @param context The context
* @param fieldName The name of the field
* @return true if the field is ambiguous
*/
protected boolean isFieldAmbiguous(ModelContext context, String fieldName)
{
boolean ambiguous = false;
// check whether there is a property and association definition
// for the given field name
if (context.getPropertyDefinitions().get(fieldName) != null &&
context.getAssociationDefinitions().get(fieldName) != null)
{
ambiguous = true;
if (logger.isWarnEnabled())
logger.warn("\"" + fieldName + "\" is ambiguous, a property and an association exists with this name," +
" prefix with either \"prop:\" or \"assoc:\" to uniquely identify the field");
}
return ambiguous;
}
/**
* Generates a model for a "transient" field.
*
* @param fieldName The name of the field
* @param template The control template to use
* @return The field model
*/
protected Field generateTransientFieldModel(String fieldName, String template)
{
Field field = new Field();
// replace colons for name and id
String name = fieldName.replace(":", "_");
field.setConfigName(fieldName);
field.setName(name);
field.setId(name);
field.setLabel(fieldName);
field.setValue("");
field.setTransitory(true);
field.setControl(new FieldControl(template));
return field;
}
/**
* Generates a model for a "transient" field.
*
* @param context The context
* @param fieldName The name of the field to be added
* @return The field model
*/
protected Field generateTransientFieldModel(ModelContext context, String fieldName,
JSONObject fieldDefinition, FormField fieldConfig) throws JSONException
{
// we can't continue without at least a control template
if (fieldConfig == null ||
fieldConfig.getControl() == null ||
fieldConfig.getControl().getTemplate() == null ||
fieldConfig.getAttributes() == null ||
(fieldConfig.getAttributes().get("set") != null && !fieldConfig.getAttributes().get("set").isEmpty()))
{
return null;
}
if (logger.isDebugEnabled())
logger.debug("Generating transient field for \"" + fieldName + "\"");
// generate the basic transient field
Field field = generateTransientFieldModel(fieldName, fieldConfig.getControl().getTemplate());
// setup parameters, if present
List<ControlParam> params = fieldConfig.getControl().getParamsAsList();
if (params.size() > 0)
{
// get the field's control
FieldControl control = field.getControl();
for (ControlParam param : params)
{
// add parameter to field control
control.getParams().put(param.getName(), param.getValue());
}
}
// apply any configured text
processFieldText(context, field, fieldDefinition, fieldConfig);
return field;
}
/**
* Processes the identification part of the field model.
*
* @param context The context
* @param field The field to be processed
* @param fieldDefinition The definition of the field to be processed
* @param fieldConfig The configuration of the field to be processed
* @throws JSONException
*/
protected void processFieldIdentification(ModelContext context, Field field,
JSONObject fieldDefinition, FormField fieldConfig) throws JSONException
{
field.setConfigName(fieldDefinition.getString(MODEL_NAME));
field.setType(fieldDefinition.getString(MODEL_TYPE));
String name = field.getConfigName();
if (field.getType().equals(ASSOCIATION))
{
// add assoc prefix if missing
if (!name.startsWith(ASSOC_PREFIX))
{
name = ASSOC_PREFIX + field.getConfigName();
}
}
else
{
// add prop prefix if missing
if (!name.startsWith(PROP_PREFIX))
{
name = PROP_PREFIX + field.getConfigName();
}
}
// replace : with _ so it can be used as JSON/JavaScript key/property
name = name.replace(":", "_");
// set the id of the field
field.setId(name);
// set name of the field (ALF-5146: escape any dots in the name)
name = name.replace(".", "#dot#");
field.setName(name);
}
/**
* Processes the "state" part of the field model i.e. disabled, mandatory
*
* @param context The context
* @param field The field to be processed
* @param fieldDefinition The definition of the field to be processed
* @param fieldConfig The configuration of the field to be processed
* @throws JSONException
*/
protected void processFieldState(ModelContext context, Field field,
JSONObject fieldDefinition, FormField fieldConfig) throws JSONException
{
// configure read-only state (but only if the field definition indicates
// that it is not a protected field)
boolean disabled = false;
if (fieldDefinition.has(MODEL_PROTECTED_FIELD))
{
disabled = fieldDefinition.getBoolean(MODEL_PROTECTED_FIELD);
}
if (!disabled && fieldConfig != null && fieldConfig.isReadOnly())
{
disabled = true;
}
field.setDisabled(disabled);
// configure mandatory state (but only if the field definition indicates
// that it is an optional field)
boolean mandatory = false;
if (fieldDefinition.has(MODEL_MANDATORY))
{
// properties will have "mandatory"
mandatory = fieldDefinition.getBoolean(MODEL_MANDATORY);
}
if (fieldDefinition.has(MODEL_ENDPOINT_MANDATORY))
{
// associations will have "endpointMandatory"
mandatory = fieldDefinition.getBoolean(MODEL_ENDPOINT_MANDATORY);
}
if (!mandatory && fieldConfig != null && fieldConfig.isMandatory())
{
mandatory = true;
}
field.setMandatory(mandatory);
// configure repeating state
if (fieldDefinition.has(MODEL_REPEATING))
{
field.setRepeating(fieldDefinition.getBoolean(MODEL_REPEATING));
}
if (fieldDefinition.has(MODEL_ENDPOINT_MANY))
{
field.setRepeating(fieldDefinition.getBoolean(MODEL_ENDPOINT_MANY));
}
// configure association direction (if appropriate)
if (fieldDefinition.has(MODEL_ENDPOINT_DIRECTION))
{
field.setEndpointDirection(fieldDefinition.getString(MODEL_ENDPOINT_DIRECTION));
}
}
/**
* Processes the "text" part of the field model i.e. label, description, help
*
* @param context The context
* @param field The field to be processed
* @param fieldDefinition The definition of the field to be processed
* @param fieldConfig The configuration of the field to be processed
* @throws JSONException
*/
protected void processFieldText(ModelContext context, Field field,
JSONObject fieldDefinition, FormField fieldConfig) throws JSONException
{
// set the initial label and description from the field definition, if present
if (fieldDefinition != null)
{
if (fieldDefinition.has(MODEL_LABEL))
{
field.setLabel(fieldDefinition.getString(MODEL_LABEL));
}
if (fieldDefinition.has(MODEL_DESCRIPTION))
{
field.setDescription(fieldDefinition.getString(MODEL_DESCRIPTION));
}
}
if (fieldConfig != null)
{
// process configured label
String configLabel = null;
if (fieldConfig.getLabelId() != null)
{
configLabel = retrieveMessage(fieldConfig.getLabelId());
}
else if (fieldConfig.getLabel() != null)
{
configLabel = fieldConfig.getLabel();
}
if (configLabel != null)
{
field.setLabel(configLabel);
}
// process configured description
String configDesc = null;
if (fieldConfig.getDescriptionId() != null)
{
configDesc = retrieveMessage(fieldConfig.getDescriptionId());
}
else if (fieldConfig.getDescription() != null)
{
configDesc = fieldConfig.getDescription();
}
if (configDesc != null)
{
field.setDescription(configDesc);
}
// process configured help text
String configHelp = null;
if (fieldConfig.getHelpTextId() != null)
{
configHelp = retrieveMessage(fieldConfig.getHelpTextId());
}
else if (fieldConfig.getHelpText() != null)
{
configHelp = fieldConfig.getHelpText();
}
if (configHelp != null)
{
field.setHelp(configHelp);
}
// Only override the default value if explicitly specified in the config
if (fieldConfig.getHelpEncodeHtml() != null)
{
field.setHelpEncodeHtml(fieldConfig.getHelpEncodeHtml().equalsIgnoreCase("true"));
}
}
}
/**
* Processes the "data" part of the field model.
*
* @param context The context
* @param field The field to be processed
* @param fieldDefinition The definition of the field to be processed
* @param fieldConfig The configuration of the field to be processed
* @throws JSONException
*/
protected void processFieldData(ModelContext context, Field field,
JSONObject fieldDefinition, FormField fieldConfig) throws JSONException
{
if (fieldDefinition.has(MODEL_DATA_TYPE))
{
field.setDataType(fieldDefinition.getString(MODEL_DATA_TYPE));
}
if (fieldDefinition.has(MODEL_ENDPOINT_TYPE))
{
field.setDataType(fieldDefinition.getString(MODEL_ENDPOINT_TYPE));
}
field.setDataKeyName(fieldDefinition.getString(MODEL_DATA_KEY_NAME));
field.setValue("");
// extract the data for the field from the 'formData' JSON object
JSONObject formDefinition = context.getFormDefinition().getJSONObject(MODEL_DATA);
if (formDefinition.has(MODEL_FORM_DATA))
{
JSONObject formData = formDefinition.getJSONObject(MODEL_FORM_DATA);
if (formData.has(field.getDataKeyName()))
{
field.setValue(formData.get(field.getDataKeyName()));
}
}
// if the value is still empty, we're in create mode and the
// field has a default value use it for initial value
if (field.getValue().equals("") && context.getMode().equals(Mode.CREATE) &&
fieldDefinition.has(MODEL_DEFAULT_VALUE))
{
field.setValue(fieldDefinition.getString(MODEL_DEFAULT_VALUE));
}
if (fieldDefinition.has(MODEL_INDEX_TOKENISATION_MODE))
{
if (fieldDefinition.getString(MODEL_INDEX_TOKENISATION_MODE).toUpperCase().equals("FALSE"))
{
field.setIndexTokenisationMode(fieldDefinition.getString(MODEL_INDEX_TOKENISATION_MODE));
}
}
}
/**
* Processes the constraints for the field.
*
* NOTE: This method MUST be called with the Field object having it's
* identification, state and text already processed.
*
* @param context The context
* @param field The field to be processed
* @param fieldDefinition The definition of the field to be processed
* @param fieldConfig The configuration of the field to be processed
* @throws JSONException
*/
protected void processFieldConstraints(ModelContext context, Field field,
JSONObject fieldDefinition, FormField fieldConfig) throws JSONException
{
// setup mandatory constraint if field is marked as such
if (!field.isDisabled())
{
if (field.isMandatory())
{
Constraint constraint = generateConstraintModel(context, field, fieldDefinition, fieldConfig, CONSTRAINT_MANDATORY);
if (constraint != null)
{
// add the constraint to the context
context.getConstraints().add(constraint);
}
}
if (fieldConfig != null && fieldConfig.getConstraintDefinitionMap() != null)
{
// add form constraints defined in custom config
Map<String, ConstraintHandlerDefinition> fieldConstraints = fieldConfig.getConstraintDefinitionMap();
for (String constraintId : fieldConstraints.keySet())
{
Constraint constraint = null;
// get the custom handler for the constraint
ConstraintHandlerDefinition customConstraintConfig = fieldConstraints.get(constraintId);
if (customConstraintConfig != null)
{
// generate and process the constraint model
constraint = generateConstraintModel(context, field, fieldConfig, constraintId, new JSONObject(), customConstraintConfig);
}
if (constraint != null)
{
// add the constraint to the context
context.getConstraints().add(constraint);
}
}
}
}
// look for model defined constraints on the field definition
if (fieldDefinition.has(MODEL_CONSTRAINTS))
{
JSONArray constraints = fieldDefinition.getJSONArray(MODEL_CONSTRAINTS);
for (int x = 0; x < constraints.length(); x++)
{
Constraint constraint = generateConstraintModel(context, field,
fieldDefinition, fieldConfig, constraints.getJSONObject(x));
if (constraint != null)
{
// add the constraint to the context
context.getConstraints().add(constraint);
}
}
}
// add a number constraint if the field has a number data type
String dataType = field.getDataType();
Map<String, ConstraintHandlerDefinition> constraintDefinitionMap = (fieldConfig == null) ? null : fieldConfig.getConstraintDefinitionMap();
if (isConstraintHandlerExist(constraintDefinitionMap, CONSTRAINT_NUMBER) ||isDataTypeNumber(dataType))
{
Constraint constraint = generateConstraintModel(context, field, fieldDefinition,
fieldConfig, CONSTRAINT_NUMBER);
if (constraint != null)
{
// if the field is repeating add a flag to indicate this
// so the client side validation handler can take the appropriate action
if (field.isRepeating())
{
constraint.getJSONParams().put("repeating", true);
}
// add the constraint to the context
context.getConstraints().add(constraint);
}
}
}
private boolean isConstraintHandlerExist(Map<String, ConstraintHandlerDefinition> constraintDefinitionMap, String constraint)
{
if (constraintDefinitionMap != null)
{
return constraintDefinitionMap.containsKey(constraint);
}
return false;
}
private boolean isDataTypeNumber(String dataType)
{
if (TYPE_INT.equals(dataType) ||TYPE_LONG.equals(dataType) ||TYPE_DOUBLE.equals(dataType)
||TYPE_FLOAT.equals(dataType))
{
return true;
}
return false;
}
/**
* Generates the model for a single constraint.
*
* @param context The context
* @param field The field to be processed
* @param fieldDefinition The definition of the field to be processed
* @param fieldConfig The configuration of the field to be processed
* @param constraintId The constraint identifier
* @return Constraint
* @throws JSONException
*/
protected Constraint generateConstraintModel(ModelContext context, Field field,
JSONObject fieldDefinition, FormField fieldConfig,
String constraintId) throws JSONException
{
// create a JSONObject containing the constraint id
JSONObject constraintDef = new JSONObject();
constraintDef.put(MODEL_TYPE, constraintId);
// generate the constraint model
return generateConstraintModel(context, field, fieldDefinition,
fieldConfig, constraintDef);
}
/**
* Generates the model for a single constraint.
*
* @param context The context
* @param field The field to be processed
* @param fieldDefinition The definition of the field to be processed
* @param fieldConfig The configuration of the field to be processed
* @param constraintDefinition The constraint definition
* @return Constraint
* @throws JSONException
*/
protected Constraint generateConstraintModel(ModelContext context, Field field,
JSONObject fieldDefinition, FormField fieldConfig,
JSONObject constraintDefinition) throws JSONException
{
Constraint constraint = null;
String constraintId = null;
JSONObject constraintParams = null;
// extract the constraint id
if (constraintDefinition.has(MODEL_TYPE))
{
constraintId = constraintDefinition.getString(MODEL_TYPE);
}
if (constraintDefinition.has(MODEL_PARAMETERS))
{
constraintParams = constraintDefinition.getJSONObject(MODEL_PARAMETERS);
}
else
{
constraintParams = new JSONObject();
}
// retrieve the default constraints configuration
ConstraintHandlersConfigElement defaultConstraintHandlers = null;
FormsConfigElement formsGlobalConfig =
(FormsConfigElement)this.configService.getGlobalConfig().getConfigElement(CONFIG_FORMS);
if (formsGlobalConfig != null)
{
defaultConstraintHandlers = formsGlobalConfig.getConstraintHandlers();
}
if (defaultConstraintHandlers == null)
{
throw new WebScriptException("Failed to locate default constraint handlers configurarion");
}
// get the default handler for the constraint
ConstraintHandlerDefinition defaultConstraintConfig =
defaultConstraintHandlers.getItems().get(constraintId);
if (defaultConstraintConfig != null)
{
// generate and process the constraint model
constraint = generateConstraintModel(context, field, fieldConfig,
constraintId, constraintParams, defaultConstraintConfig);
processFieldConstraintControl(context, field, fieldConfig, constraint);
processFieldConstraintHelp(context, field, fieldConfig, constraint);
}
else if (logger.isWarnEnabled())
{
logger.warn("No default constraint configuration found for \"" + constraintId +
"\" constraint whilst processing field \"" + field.getConfigName() + "\"");
}
return constraint;
}
/**
* Generates the model for a single constraint.
*
* @param context The context
* @param field The field to be processed
* @param fieldConfig The configuration of the field to be processed
* @param constraintId The constraint identifier
* @param constraintParams The constraint parameters
* @param defaultConstraintConfig ConstraintHandlerDefinition
* @return The constraint moel
* @throws JSONException
*/
protected Constraint generateConstraintModel(ModelContext context, Field field, FormField fieldConfig,
String constraintId, JSONObject constraintParams,
ConstraintHandlerDefinition defaultConstraintConfig) throws JSONException
{
// get the validation handler from the config
String validationHandler = defaultConstraintConfig.getValidationHandler();
Constraint constraint = new Constraint(field.getId(), constraintId,
validationHandler, constraintParams);
if (defaultConstraintConfig.getEvent() != null)
{
constraint.setEvent(defaultConstraintConfig.getEvent());
}
else
{
constraint.setEvent(DEFAULT_CONSTRAINT_EVENT);
}
// look for an overridden message in the field's constraint config,
// if none found look in the default constraint config
String constraintMsg = null;
if (fieldConfig != null &&
fieldConfig.getConstraintDefinitionMap().get(constraintId) != null)
{
ConstraintHandlerDefinition fieldConstraintConfig =
fieldConfig.getConstraintDefinitionMap().get(constraintId);
if (fieldConstraintConfig.getMessageId() != null)
{
constraintMsg = retrieveMessage(fieldConstraintConfig.getMessageId());
}
else if (fieldConstraintConfig.getMessage() != null)
{
constraintMsg = fieldConstraintConfig.getMessage();
}
// look for overridden validation handler
if (fieldConstraintConfig.getValidationHandler() != null)
{
constraint.setValidationHandler(fieldConstraintConfig.getValidationHandler());
}
// look for overridden event
if (fieldConstraintConfig.getEvent() != null)
{
constraint.setEvent(fieldConstraintConfig.getEvent());
}
}
else if (defaultConstraintConfig.getMessageId() != null)
{
constraintMsg = retrieveMessage(defaultConstraintConfig.getMessageId());
}
else if (defaultConstraintConfig.getMessage() != null)
{
constraintMsg = defaultConstraintConfig.getMessage();
}
if (constraintMsg == null)
{
constraintMsg = retrieveMessage(validationHandler + ".message");
}
// add the message if there is one
if (constraintMsg != null)
{
constraint.setMessage(constraintMsg);
}
return constraint;
}
/**
* Processes the given constraint to ensure the field's control
* adheres to the constraint.
*
* @param context The context
* @param field The field to be processed
* @param fieldConfig The configuration of the field to be processed
* @param constraint The constraint
* @throws JSONException
*/
protected void processFieldConstraintControl(ModelContext context, Field field,
FormField fieldConfig, Constraint constraint) throws JSONException
{
// process special constraint behaviour
if (CONSTRAINT_LIST.equals(constraint.getId()))
{
// if the constraint is the list of values constraint, force the control
// template to be selectone.ftl or selectmany.ftl depending on whether
// the field has multiple values, but only if an overridden control has
// not been supplied
if (fieldConfig == null || fieldConfig.getControl() == null ||
fieldConfig.getControl().getTemplate() == null)
{
if (field.isRepeating())
{
field.getControl().setTemplate(CONTROL_SELECT_MANY);
}
else
{
field.getControl().setTemplate(CONTROL_SELECT_ONE);
}
}
// setup the options string and set as control params, but only if the control
// does not already have an "options" parameter
if (field.getControl().getParams().containsKey(CONTROL_PARAM_OPTIONS) == false)
{
JSONArray options = constraint.getJSONParams().getJSONArray("allowedValues");
List<String> optionsList = new ArrayList<String>(options.length());
for (int x = 0; x < options.length(); x++)
{
optionsList.add(options.getString(x));
}
// Sort the options based on the label...
if (fieldConfig != null && fieldConfig.isSorted())
{
Collections.sort(optionsList, new OptionsComparator());
}
// ALF-7961: don't use a comma as the list separator
field.getControl().getParams().put(CONTROL_PARAM_OPTIONS,
StringUtils.collectionToDelimitedString(optionsList, DELIMITER));
field.getControl().getParams().put(CONTROL_PARAM_OPTION_SEPARATOR, DELIMITER);
}
}
else if (CONSTRAINT_LENGTH.equals(constraint.getId()))
{
int maxLength = -1;
if (constraint.getJSONParams().has(MODEL_MAX_LENGTH))
{
maxLength = constraint.getJSONParams().getInt(MODEL_MAX_LENGTH);
}
// if the constraint is the length constraint, pass the maxLength
// parameter to the control if appropriate
if (maxLength != -1)
{
field.getControl().getParams().put("maxLength", Integer.toString(maxLength));
// set the crop argument to true so that textareas also restrict characters
constraint.getJSONParams().put("crop", true);
}
}
else if (CONSTRAINT_REGEX.equals(constraint.getId()))
{
// if the cm:name property is being processed switch the validation handler
// to the JavaScript specific nodeName handler.
if (CM_NAME_PROP.equals(field.getName()))
{
constraint.setValidationHandler(CONSTRAINT_FILE_NAME_HANDLER);
constraint.setJSONParams(new JSONObject());
}
}
}
/**
* Processes the given constraint to add help text to the field's control
* if relevant.
*
* @param context The context
* @param field The field to be processed
* @param fieldConfig The configuration of the field to be processed
* @param constraint The constraint
* @throws JSONException
*/
protected void processFieldConstraintHelp(ModelContext context, Field field,
FormField fieldConfig, Constraint constraint) throws JSONException
{
// add help text appropriate for the constraint, but only if the
// field doesn't already have any help text set
if (field.getHelp() == null)
{
if (CONSTRAINT_LENGTH.equals(constraint.getId()))
{
String text = retrieveMessage(CONSTRAINT_MSG_LENGTH,
constraint.getJSONParams().getInt("minLength"),
constraint.getJSONParams().getInt("maxLength"));
field.setHelp(text);
}
else if (CONSTRAINT_MINMAX.equals(constraint.getId()))
{
String text = retrieveMessage(CONSTRAINT_MSG_MINMAX,
constraint.getJSONParams().getInt("minValue"),
constraint.getJSONParams().getInt("maxValue"));
field.setHelp(text);
}
else if (CONSTRAINT_NUMBER.equals(constraint.getId()))
{
field.setHelp(retrieveMessage(CONSTRAINT_MSG_NUMBER));
}
}
}
/**
* Processes the control for the field.
*
* @param context The context
* @param field The field to be processed
* @param fieldDefinition The definition of the field to be processed
* @param fieldConfig The configuration of the field to be processed
* @throws JSONException
*/
protected void processFieldControl(ModelContext context, Field field,
JSONObject fieldDefinition, FormField fieldConfig) throws JSONException
{
FieldControl control = null;
// retrieve the default controls configuration
DefaultControlsConfigElement defaultControls = null;
FormsConfigElement formsGlobalConfig =
(FormsConfigElement)this.configService.getGlobalConfig().getConfigElement(CONFIG_FORMS);
if (formsGlobalConfig != null)
{
defaultControls = formsGlobalConfig.getDefaultControls();
}
// ensure we found the default controls config
if (defaultControls == null)
{
throw new WebScriptException("Failed to locate default controls configuration");
}
boolean isPropertyField = !ASSOCIATION.equals(fieldDefinition.getString(MODEL_TYPE));
Control defaultControlConfig = null;
if (isPropertyField)
{
// get the default control for the property data type
defaultControlConfig = defaultControls.getItems().get(
fieldDefinition.getString(MODEL_DATA_TYPE));
// for backwards compatibility also check d:<dataType>
if (defaultControlConfig == null)
{
defaultControlConfig = defaultControls.getItems().get(
OLD_DATA_TYPE_PREFIX + fieldDefinition.getString(MODEL_DATA_TYPE));
}
}
else
{
// look for a specific type based default control for associations
defaultControlConfig = defaultControls.getItems().get(
ASSOCIATION + ":" + fieldDefinition.getString(MODEL_ENDPOINT_TYPE));
// get the generic default control for associations if a type specific one was not found
if (defaultControlConfig == null)
{
defaultControlConfig = defaultControls.getItems().get(ASSOCIATION);
}
}
// see if the fieldConfig already has a template defined, if not
// retrieve the default template for the field's data type
if (fieldConfig != null && fieldConfig.getControl() != null &&
fieldConfig.getControl().getTemplate() != null)
{
control = new FieldControl(fieldConfig.getControl().getTemplate());
}
else
{
if (defaultControlConfig != null)
{
control = new FieldControl(defaultControlConfig.getTemplate());
}
else if (logger.isWarnEnabled())
{
if (isPropertyField)
{
logger.warn("No default control found for data type \"" +
fieldDefinition.getString(MODEL_DATA_TYPE) +
"\" whilst processing field \"" +
fieldDefinition.getString(MODEL_NAME) + "\"");
}
else
{
logger.warn("No default control found for associations" +
"\" whilst processing field \"" +
fieldDefinition.getString(MODEL_NAME) + "\"");
}
}
}
// send any type parameters returned from the server to the control
if (isPropertyField && control != null &&
fieldDefinition.has(MODEL_DATA_TYPE_PARAMETERS))
{
control.getParams().put(MODEL_DATA_TYPE_PARAMETERS,
fieldDefinition.get(MODEL_DATA_TYPE_PARAMETERS).toString());
}
// get control parameters for the default control (if there is one)
if (defaultControlConfig != null && control != null)
{
List<ControlParam> paramsConfig = defaultControlConfig.getParamsAsList();
for (ControlParam param : paramsConfig)
{
control.getParams().put(param.getName(), param.getValue());
}
}
// get overridden control parameters (if there are any)
if (fieldConfig != null && control != null)
{
List<ControlParam> paramsConfig = fieldConfig.getControl().getParamsAsList();
for (ControlParam param : paramsConfig)
{
control.getParams().put(param.getName(), param.getValue());
}
}
// finally set the control model on the field model
field.setControl(control);
}
/**
* Processes the field for content. This method is used when a content field
* is being used in a form where JavaScript is disabled and thus AJAX is
* unavailable to retrieve the content, it must therefore be done server side.
*
* @param context The context
* @param field The field to be processed
* @param fieldDefinition The definition of the field to be processed
* @param fieldConfig The configuration of the field to be processed
* @throws JSONException
*/
protected void processFieldContent(ModelContext context, Field field,
JSONObject fieldDefinition, FormField fieldConfig) throws JSONException
{
// if the field is a content field and JavaScript is disabled
// we need to retrieve the content here and store in model
if (context.getFormUIModel().get(MODEL_CAPABILITIES) != null && "content".equals(field.getDataType()))
{
// NOTE: In the future when other capabilties are added the 'javascript'
// flag will need to be checked, for now it's the only reason
// the capabilities object will be present so a check is redundant
if (logger.isDebugEnabled())
logger.debug("Retrieving content for \"" + field.getConfigName() + "\" as JavaScript is disabled");
// get the nodeRef of the content and then the content itself
String nodeRef = getParameter(context.getRequest(), "itemId");
try
{
ConnectorService connService = FrameworkUtil.getConnectorService();
RequestContext requestContext = ThreadLocalRequestContext.getRequestContext();
String currentUserId = requestContext.getUserId();
HttpSession currentSession = ServletUtil.getSession(true);
Connector connector = connService.getConnector(ENDPOINT_ID, currentUserId, currentSession);
// call the form service
Response response = connector.call("/api/node/content/" + nodeRef.replace("://", "/"));
if (response.getStatus().getCode() == Status.STATUS_OK)
{
field.setContent(response.getText());
}
}
catch (Exception e)
{
if (logger.isErrorEnabled())
logger.error("Failed to get field content: ", e);
}
}
}
/**
* Generates the "error" model used when an error occurs.
*
* @param errorResponse Response object representing the error
* @return The "error" model
*/
protected Map<String, Object> generateErrorModel(Response errorResponse)
{
return generateErrorModel(errorResponse, null);
}
/**
* Generates the "error" model used when an error occurs.
*
* @param errorResponse Response object representing the error
* @param errorKey String
* @return The "error" model
*/
protected Map<String, Object> generateErrorModel(Response errorResponse, String errorKey)
{
String error = "";
// retrieve and log the error
try
{
JSONObject json = new JSONObject(new JSONTokener(errorResponse.getResponse()));
if (json.has(MODEL_MESSAGE))
{
error = json.getString(MODEL_MESSAGE);
// Common AccessDeniedException is reported as a 500 server error from the repository
if ((error.indexOf("org.alfresco.repo.security.permissions.AccessDeniedException") == -1) &&
(errorKey == null || errorKey.isEmpty()))
{
if (logger.isErrorEnabled())
logger.error(error);
}
}
}
catch (JSONException je)
{
error= "";
}
if (errorKey == null || errorKey.isEmpty())
{
errorKey = MSG_DEFAULT_FORM_ERROR;
}
String id = errorKey + "." + errorResponse.getStatus().getCode();
error = retrieveMessage(id);
if (error.equals(id))
{
// use key if key+"."+status is not found
error = retrieveMessage(errorKey);
}
// create model with error
Map<String, Object> model = new HashMap<String, Object>(1);
model.put(MODEL_ERROR, error);
return model;
}
/**
* Dumps the given form UI model to debug output (when debug is enabled).
*
* @param model The form UI model to dump
*/
protected void dumpFormUIModel(Map<String, Object> model)
{
if (logger.isDebugEnabled())
{
logger.debug("formUIModel = " + dumpMap(model, INDENT));
}
}
@SuppressWarnings("unchecked")
protected String dumpMap(Map<String, Object> map, String indent)
{
StringBuilder builder = new StringBuilder();
// start
builder.append("\n");
if (indent.length() > INDENT.length())
{
builder.append(indent.substring(INDENT.length()));
}
builder.append("{");
// name & values
boolean firstKey = true;
for (String key : map.keySet())
{
if (firstKey)
firstKey = false;
else
builder.append(",");
builder.append("\n");
builder.append(indent);
builder.append(key);
builder.append(": ");
Object value = map.get(key);
if (value instanceof String)
{
builder.append("\"");
builder.append(value);
builder.append("\"");
}
else if (value instanceof Map)
{
builder.append(dumpMap((Map)value, indent + INDENT));
}
else if (value instanceof List)
{
boolean firstItem = true;
builder.append("\n").append(INDENT).append("[");
for (Object item : ((List)value))
{
if (firstItem)
firstItem = false;
else
builder.append(",");
builder.append("\n").append(INDENT).append(INDENT);
builder.append(item);
}
builder.append("\n").append(INDENT).append("]");
}
else
{
builder.append(value);
}
}
// end
builder.append("\n");
if (indent.length() > INDENT.length())
{
builder.append(indent.substring(INDENT.length()));
}
builder.append("}");
return builder.toString();
}
/**
* Inner class used to hold all the context required to generate the model
* and the model itself.
*
* <br/><br/>author Gavin Cornwell
*/
protected class ModelContext
{
private Map<String, Object> formUIModel;
private Map<String, JSONObject> propDefs;
private Map<String, JSONObject> assocDefs;
private WebScriptRequest request;
private Mode mode;
private JSONObject formDefinition;
private FormConfigElement formConfig;
private List<Constraint> constraints;
private List<Element> structure;
private Map<String, Field> fields;
protected ModelContext(WebScriptRequest request, Mode mode,
JSONObject formDefinition, FormConfigElement formConfig)
{
this.request = request;
this.mode = mode;
this.formDefinition = formDefinition;
this.formConfig = formConfig;
cacheFieldDefinitions();
}
public void cacheFieldDefinitions()
{
this.propDefs = new HashMap<String, JSONObject>(8);
this.assocDefs = new HashMap<String, JSONObject>(8);
try
{
JSONObject data = this.formDefinition.getJSONObject(MODEL_DATA);
JSONObject definition = data.getJSONObject(MODEL_DEFINITION);
JSONArray fields = definition.getJSONArray(MODEL_FIELDS);
for (int x = 0; x < fields.length(); x++)
{
JSONObject fieldDef = fields.getJSONObject(x);
if (fieldDef.getString(MODEL_TYPE).equals(PROPERTY))
{
this.propDefs.put(fieldDef.getString(MODEL_NAME), fieldDef);
}
else if (fieldDef.getString(MODEL_TYPE).equals(ASSOCIATION))
{
this.assocDefs.put(fieldDef.getString(MODEL_NAME), fieldDef);
}
}
}
catch (JSONException je)
{
if (logger.isErrorEnabled())
logger.error("Failed to cache field definitions", je);
}
}
public void setFormUIModel(Map<String, Object> formUIModel)
{
this.formUIModel = formUIModel;
}
public Map<String, Object> getFormUIModel()
{
return this.formUIModel;
}
public Map<String, JSONObject> getPropertyDefinitions()
{
return this.propDefs;
}
public Map<String, JSONObject> getAssociationDefinitions()
{
return this.assocDefs;
}
public WebScriptRequest getRequest()
{
return this.request;
}
public Mode getMode()
{
return this.mode;
}
public JSONObject getFormDefinition()
{
return this.formDefinition;
}
public FormConfigElement getFormConfig()
{
return this.formConfig;
}
public List<Constraint> getConstraints()
{
if (this.constraints == null)
{
this.constraints = new ArrayList<Constraint>(2);
}
return this.constraints;
}
public List<Element> getStructure()
{
if (this.structure == null)
{
this.structure = new ArrayList<Element>(4);
}
return this.structure;
}
public Map<String, Field> getFields()
{
if (this.fields == null)
{
this.fields = new HashMap<String, Field>(8);
}
return this.fields;
}
}
/**
* Base inner class to represent form elements i.e a field or set
*
* NOTE: This class has to be public for the template engine to
* access the object correctly.
*
* <br/><br/>author Gavin Cornwell
*/
public abstract class Element
{
protected String kind;
protected String id;
public String getKind()
{
return this.kind;
}
public String getId()
{
return this.id;
}
@Override
public String toString()
{
StringBuilder builder = new StringBuilder();
builder.append(this.kind);
builder.append("(");
builder.append(this.id);
builder.append(")");
return builder.toString();
}
}
/**
* Represents a pointer to a field, used in the form UI model.
*/
public class FieldPointer extends Element
{
FieldPointer(String id)
{
this.kind = FIELD;
this.id = id;
}
}
/**
* Represents a set of fields and/or nested sets.
*/
public class Set extends Element
{
protected String appearance;
protected String template;
protected String label;
protected List<Element> children;
Set(FormSet setConfig)
{
this.kind = SET;
this.id = setConfig.getSetId();
this.appearance = setConfig.getAppearance();
this.template = setConfig.getTemplate();
this.label = discoverSetLabel(setConfig);
this.children = new ArrayList<Element>(4);
}
Set(String id, String label)
{
this.kind = SET;
this.id = id;
this.label = label;
this.children = new ArrayList<Element>(1);
}
public void addChild(Element child)
{
this.children.add(child);
}
public String getAppearance()
{
return this.appearance;
}
public String getTemplate()
{
return this.template;
}
public String getLabel()
{
return this.label;
}
public List<Element> getChildren()
{
return this.children;
}
@Override
public String toString()
{
StringBuilder buffer = new StringBuilder();
buffer.append(this.kind);
buffer.append("(id=").append(this.id);
buffer.append(" appearance=").append(this.appearance);
buffer.append(" label=").append(this.label);
buffer.append(" template=").append(this.template);
buffer.append(" children=[");
boolean first = true;
for (Element child : this.children)
{
if (first)
first = false;
else
buffer.append(", ");
buffer.append(child);
}
buffer.append("])");
return buffer.toString();
}
}
/**
* Represents a field on a form.
*/
public class Field extends Element
{
protected String name;
protected String configName;
protected String label;
protected String description;
protected String help;
protected boolean helpEncodeHtml = true;
protected FieldControl control;
protected String dataKeyName;
protected String dataType;
protected String type;
protected String content;
protected String endpointDirection;
protected Object value;
protected boolean disabled = false;
protected boolean mandatory = false;
protected boolean transitory = false;
protected boolean repeating = false;
protected String indexTokenisationMode;
Field()
{
this.kind = FIELD;
}
public void setId(String id)
{
this.id = id;
}
public String getConfigName()
{
return this.configName;
}
public void setConfigName(String configName)
{
this.configName = configName;
}
public FieldControl getControl()
{
return this.control;
}
public void setControl(FieldControl control)
{
this.control = control;
}
public String getDataKeyName()
{
return this.dataKeyName;
}
public void setDataKeyName(String dataKeyName)
{
this.dataKeyName = dataKeyName;
}
public String getDataType()
{
return this.dataType;
}
public void setDataType(String dataType)
{
this.dataType = dataType;
}
public String getDescription()
{
return this.description;
}
public void setDescription(String description)
{
this.description = description;
}
public boolean isDisabled()
{
return this.disabled;
}
public void setDisabled(boolean disabled)
{
this.disabled = disabled;
}
public String getLabel()
{
return this.label;
}
public void setLabel(String label)
{
this.label = label;
}
public boolean isMandatory()
{
return this.mandatory;
}
public void setMandatory(boolean mandatory)
{
this.mandatory = mandatory;
}
public boolean isTransitory()
{
return this.transitory;
}
public void setTransitory(boolean transitory)
{
this.transitory = transitory;
}
public String getName()
{
return this.name;
}
public void setName(String name)
{
this.name = name;
}
public boolean isRepeating()
{
return this.repeating;
}
public void setRepeating(boolean repeating)
{
this.repeating = repeating;
}
public String getType()
{
return this.type;
}
public void setType(String type)
{
this.type = type;
}
public Object getValue()
{
return this.value;
}
public void setValue(Object value)
{
this.value = value;
}
public String getContent()
{
return this.content;
}
public void setContent(String content)
{
this.content = content;
}
public String getHelp()
{
return this.help;
}
public void setHelp(String help)
{
this.help = help;
}
public boolean getHelpEncodeHtml()
{
return this.helpEncodeHtml;
}
public void setHelpEncodeHtml(boolean encode)
{
this.helpEncodeHtml = encode;
}
public String getEndpointDirection()
{
return this.endpointDirection;
}
public void setEndpointDirection(String endpointDirection)
{
this.endpointDirection = endpointDirection;
}
public String getEndpointType()
{
return getDataType();
}
public boolean isEndpointMandatory()
{
return this.mandatory;
}
public boolean isEndpointMany()
{
return this.repeating;
}
public String getIndexTokenisationMode()
{
return indexTokenisationMode;
}
public void setIndexTokenisationMode(String indexTokenisationMode)
{
this.indexTokenisationMode = indexTokenisationMode;
}
@Override
public String toString()
{
StringBuilder buffer = new StringBuilder();
buffer.append(this.kind);
buffer.append("(id=").append(this.id);
buffer.append(" name=").append(this.name);
buffer.append(" configName=").append(this.configName);
buffer.append(" type=").append(this.type);
buffer.append(" value=").append(this.value);
buffer.append(" label=").append(this.label);
buffer.append(" description=").append(this.description);
buffer.append(" help=").append(this.help);
buffer.append(" helpEncodeHtml=").append(this.helpEncodeHtml);
buffer.append(" dataKeyName=").append(this.dataKeyName);
buffer.append(" dataType=").append(this.dataType);
buffer.append(" endpointDirection=").append(this.endpointDirection);
buffer.append(" disabled=").append(this.disabled);
buffer.append(" mandatory=").append(this.mandatory);
buffer.append(" repeating=").append(this.repeating);
buffer.append(" transitory=").append(this.transitory);
buffer.append(" indexTokenisationMode=").append(this.indexTokenisationMode);
buffer.append(" ").append(this.control);
buffer.append(")");
return buffer.toString();
}
}
/**
* Represents the control used by a form field.
*/
public class FieldControl
{
protected String template;
protected Map<String, String> params;
FieldControl(String template)
{
this.template = template;
this.params = new HashMap<String, String>(4);
}
public String getTemplate()
{
return this.template;
}
public void setTemplate(String template)
{
this.template = template;
}
public Map<String, String> getParams()
{
return this.params;
}
@Override
public String toString()
{
StringBuilder buffer = new StringBuilder();
buffer.append("control(template=").append(this.template);
buffer.append(" params=").append(this.params);
buffer.append(")");
return buffer.toString();
}
}
/**
* Represents a field constraint.
*/
public class Constraint
{
private String fieldId;
private String id;
private String validationHandler;
private JSONObject params;
private String message;
private String event;
Constraint(String fieldId, String id, String handler, JSONObject params)
{
this.fieldId = fieldId;
this.id = id;
this.validationHandler = handler;
this.params = params;
}
public String getFieldId()
{
return this.fieldId;
}
public String getId()
{
return this.id;
}
public String getValidationHandler()
{
return this.validationHandler;
}
public void setValidationHandler(String validationHandler)
{
this.validationHandler = validationHandler;
}
/**
* Returns the parameters formatted as a JSON string.
*
* @return String
*/
public String getParams()
{
if (this.params == null)
{
this.params = new JSONObject();
}
return this.params.toString();
}
public JSONObject getJSONParams()
{
return this.params;
}
public void setJSONParams(JSONObject params)
{
this.params = params;
}
public String getMessage()
{
return this.message;
}
public void setMessage(String message)
{
this.message = message;
}
public String getEvent()
{
return this.event;
}
public void setEvent(String event)
{
this.event = event;
}
@Override
public String toString()
{
StringBuilder buffer = new StringBuilder();
buffer.append("constraint(fieldId=").append(this.fieldId);
buffer.append(" id=").append(this.id);
buffer.append(" validationHandler=").append(this.validationHandler);
buffer.append(" event=").append(this.event);
buffer.append(" message=").append(this.message);
buffer.append(")");
return buffer.toString();
}
}
/**
* Helper class used to retrieve localized messages.
*/
protected class MessageHelper extends AbstractMessageHelper
{
public MessageHelper(WebScript webscript)
{
super(webscript);
}
public String get(final String id, final Object... args)
{
return this.resolveMessage(id, args);
}
}
}
</pre>
<b>form.get.html.ftl</b>
<br />
<pre class="brush: xml" name="xml">
<@standalone>
<@markup id="css" >
<#include "form.css.ftl"/>
</@>
<@markup id="js">
<#include "form.js.ftl"/>
</@>
<@markup id="widgets">
<@createWidgets/>
</@>
<@markup id="html">
<@uniqueIdDiv>
<#import "form.lib.ftl" as formLib />
<#if error?exists>
<div class="error">
${error}</div>
<#elseif form?exists>
<#assign formId=args.htmlid?js_string?html + "-form">
<#assign formUI><#if args.formUI??>${args.formUI}<#else>true</#if></#assign>
<#if form.viewTemplate?? && form.mode == "view">
<#include "${form.viewTemplate}" />
<#elseif form.editTemplate?? && form.mode == "edit">
<#include "${form.editTemplate}" />
<#elseif form.createTemplate?? && form.mode == "create">
<#include "${form.createTemplate}" />
<#else>
<#if formUI == "true">
<@formLib.renderFormsRuntime formId=formId />
</#if>
<@formLib.renderFormContainer formId=formId>
<#list form.structure as item>
<#if item.kind == "set">
<#if item.children?size > 0>
<@formLib.renderSet set=item />
</#if>
<#else>
<@formLib.renderField field=form.fields[item.id] />
</#if>
</#list>
</@>
</#if>
<#else>
<div class="form-container">
${msg("form.not.present")}</div>
</#if>
</@>
</@>
</@>
</pre>
<div style="text-align: justify;">
The core part for form engine start with the line number 16 in above file.It is importing the free marker library form.lib.ftl, which contains the macros for rendering the form.Whenever the form is opened in alfresco share, there are some parameters in it.One of the important parameter which is getting passed is form mode.Based on the mode of form, it is rendering the form.If the mode is view it will only render the field name and values.How it will render this field name and field value , that is dependent on the field template.Based on passed form.mode parameter, which is passed while opening form, it will include the template.If the template is defined inside form configuration, then it will take that template.This is executed from line 25 to 47.
</div>
<div style="text-align: justify;">
Last else part (@ line 31), contains the interesting code.This is what it is rendering if there is no custom template defined inside the form configuration.It is calling the freemarker macros defined inside the form.lib.ftl. This line <@formLib.renderFormContainer formId=formId> will render the form container div element.
</div>
<div style="text-align: justify;">
<b><br /></b>
<b>form.js.ftl and form.css.ftl</b><br />
Includes all the css and javascript dependancies.</div>
<div style="text-align: justify;">
<b>form.get.properties.*</b></div>
<div style="text-align: justify;">
Configurations for I18N.<br />
<br /></div>
<div style="text-align: justify;">
<b>form.lib.ftl</b></div>
<div style="text-align: justify;">
form.lib.ftl contains the freemarker macros which are helpfull in rendering the form.Let's have look on each macro.<br />
<br />
<pre class="brush: xml" name="xml"><#macro renderFormsRuntime formId>
<script type="text/javascript">//<![CDATA[
new Alfresco.FormUI("${formId}", "${args.htmlid?js_string}").setOptions(
{
mode: "${form.mode}",
<#if form.mode == "view">
arguments:
{
itemKind: "${(form.arguments.itemKind!"")?js_string}",
itemId: "${(form.arguments.itemId!"")?js_string}",
formId: "${(form.arguments.formId!"")?js_string}"
}
<#else>
enctype: "${form.enctype}",
fields:
[
<#list form.fields?keys as field>
{
id : "${form.fields[field].id?js_string}"
}
<#if field_has_next>,</#if>
</#list>
],
fieldConstraints:
[
<#list form.constraints as constraint>
{
fieldId : "${args.htmlid?js_string}_${constraint.fieldId}",
handler : ${constraint.validationHandler},
params : ${constraint.params},
event : "${constraint.event}",
message : <#if constraint.message??>"${constraint.message?js_string}"<#else>null</#if>
}
<#if constraint_has_next>,</#if>
</#list>
],
disableSubmitButton: <#if args.disableSubmitButton??>${args.disableSubmitButton?js_string}<#else>false</#if>
</#if>
}).setMessages(
${messages}
);
//]]></script>
</#macro>
</pre>
<br />
Macor renderFormsRuntime , is creating an object of Alfresco.FormUI. There are certain parameters ,which is getting initialized after it creates an object of FormUI.
<br />
<ol>
<li>mode: Mode of the form in which it will be opened.(Create,View,Edit).</li>
<li>arguments: itemKind is used for locating form processor,itemId can be content type,aspect type or it can be something else based on value of itemKind.formId is id of form.</li>
<li>enctype: encoding type of form</li>
<li>fields:It will initialize all fields id in array.</li>
<li>fieldConstraints:It will initialize all constraints, which are defined inside the form configurations(share-config-custom.xml).When user is submitting form,this all constrains are getting validated, In case of failure it will not submit form.</li>
<li>diableSubmitButton: Self explanatory</li>
</ol>
<div>
<br /></div>
<pre class="brush:xml" name:="" xml=""><#macro renderFormContainer formId>
<div id="${formId}-container" class="form-container">
<#if form.showCaption?? && form.showCaption>
<div id="${formId}-caption" class="caption"><span class="mandatory-indicator">*</span>${msg("form.required.fields")}</div>
</#if>
<#if form.mode != "view">
<form id="${formId}" method="${form.method}" accept-charset="utf-8" enctype="${form.enctype}" action="${form.submissionUrl?html}">
</#if>
<#if form.mode == "create" && form.destination?? && form.destination?length &gt; 0>
<input id="${formId}-destination" name="alf_destination" type="hidden" value="${form.destination?html}" />
</#if>
<#if form.mode != "view" && form.redirect?? && form.redirect?length &gt; 0>
<input id="${formId}-redirect" name="alf_redirect" type="hidden" value="${form.redirect?html}" />
</#if>
<div id="${formId}-fields" class="form-fields">
<#nested>
</div>
<#if form.mode != "view">
<@renderFormButtons formId=formId />
</form>
</#if>
</div>
</#macro>
</pre>
<pre class="brush:xml" name:="" xml=""></pre>
renderFormContainer macro will render the form container.The only things which need to be explained will be the last condition.That is if the form mode is not view than we need to render submit and cancel button otherwise not.
</div>
<br />
<br />
<pre class="brush :xml" name="xml"><#macro renderFormButtons formId>
<div id="${formId}-buttons" class="form-buttons">
<#if form.showSubmitButton?? && form.showSubmitButton>
<input id="${formId}-submit" type="submit" value="${msg("form.button.submit.label")}" />&nbsp;
</#if>
<#if form.showResetButton?? && form.showResetButton>
<input id="${formId}-reset" type="reset" value="${msg("form.button.reset.label")}" />&nbsp;
</#if>
<#if form.showCancelButton?? && form.showCancelButton>
<input id="${formId}-cancel" type="button" value="${msg("form.button.cancel.label")}" />
</#if>
</div>
</#macro>
</pre>
This will render the form buttons.Generally there is no need of reset button.But if it requires then we can have it by passing parameter.<br />
<br />
<pre class="brush :xml" name="xml"><#macro renderField field>
<#if field.control?? && field.control.template??>
<#assign fieldHtmlId=args.htmlid?html + "_" + field.id?html >
<#include "${field.control.template}" />
</#if>
</#macro>
</pre>
This will render the field template which is defined inside the form configuration file.<br />
<br />
<pre class="brush :xml" name="xml"><#macro renderSet set>
<div class="set">
<#if set.appearance??>
<#if set.appearance == "fieldset">
<fieldset><legend>${set.label}</legend>
<#elseif set.appearance == "bordered-panel">
<div class="set-bordered-panel">
<div class="set-bordered-panel-heading">${set.label}</div>
<div class="set-bordered-panel-body">
<#elseif set.appearance == "panel">
<div class="set-panel">
<div class="set-panel-heading">${set.label}</div>
<div class="set-panel-body">
<#elseif set.appearance == "title">
<div class="set-title">${set.label}</div>
<#elseif set.appearance == "whitespace">
<div class="set-whitespace"></div>
</#if>
</#if>
<#if set.template??>
<#include "${set.template}" />
<#else>
<#list set.children as item>
<#if item.kind == "set">
<@renderSet set=item />
<#else>
<@renderField field=form.fields[item.id] />
</#if>
</#list>
</#if>
<#if set.appearance??>
<#if set.appearance == "fieldset">
</fieldset>
<#elseif set.appearance == "panel" || set.appearance == "bordered-panel">
</div>
</div>
</#if>
</#if>
</div>
</#macro>
</pre>
<div>
<br /></div>
If there are some grouping of field inside the form configuration.This is being handled by renderSet macro.There are certain appearance which we can set for grouping fields in ui.Those are fieldset,bordered-panel,panel,title and whitespace.<br />
<br />
<pre class="brush :xml" name="xml"><#macro renderFieldHelp field>
<#if field.help?? && field.help?length &gt; 0>
<span class="help-icon">
<img id="${fieldHtmlId}-help-icon" src="${url.context}/res/components/form/images/help.png" title="${msg("form.field.help")}" tabindex="0"/>
</span>
<div class="help-text" id="${fieldHtmlId}-help"><#if field.helpEncodeHtml>${field.help?html}<#else>${stringUtils.stripUnsafeHTML(field.help)}</#if></div>
</#if>
</#macro>
</pre>
<div style="text-align: justify;">
This will render helpicon on particular field.This macro is not used insde the form.get.html.ftl.It is used inside all the field template.</div>
</div>
<div class="blogger-post-footer">https://scontent-b-mxp.xx.fbcdn.net/hphotos-xap1/v/t1.0-9/10675541_896261013719814_5601513019470361090_n.jpg?oh=741b05a81becaae8bce36db141948a4a&oe=5531762A</div>Krutik Jayswalhttp://www.blogger.com/profile/16691396948811505379noreply@blogger.com0Pune, Maharashtra, India18.5204303 73.85674369999992518.2795358 73.534020199999929 18.7613248 74.17946719999992tag:blogger.com,1999:blog-2571457445842624811.post-14396968368796429392018-05-27T12:16:00.000-07:002018-05-27T12:27:32.518-07:00Working with List/Array and HashMap in FreeMarker <div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
Its a normal thing that we get confused between looping when we are using list, hashmap or array in freemarker .As the syntax differ for each things in freemarker. It also happens that when we want to generate JSON from java collection, we need to append comma on each iteration except the last one.Identifying an last iteration is also an issue when we use freemarker. Its not much difficult, its just we are not concentrating on syntax.</div>
<br />
So lets look on the syntax of each one.<br />
<br />
<h6>
Iterating Array or Sequence(generally its any type of List) in freemarker</h6>
<pre class="brush: xml" name="html">
<ul>
<#list ArrayOrListOfusers as user>
<li>${user}
</#list>
</ul>
</pre>
<br />
<h6>
Iterating Hashmap in freemarker</h6>
<br />
When we are dealing with hashmap type of object, There are 2 values getting stored in side an item of hashmap.There are some technical scenarios in which we need only list values , We need only key of hashmap etc...
<br />
<li>list HashMap?keys as key ==> In this loop, variable <b>key</b> will represent the keys in haspmap
</li>
<li>list HashMap?values as val==> In this loop, variable <b>val</b> will represent the Values in haspmap
</li>
<li>list HashMap as key,val==> In this loop, variable <b>key</b> represents the value of key in hash map and <b>val</b> will represent the Value of values in haspmap
<pre class="brush: xml" name="html">
<ul>
<#list HashMap as keyItem,valItem>
<li>${key}=${val}
</#list>
</ul>
</pre>
There are many cases where we need to append comma after each iteration and on the last iteration we need to ignore it.This is kind of bit tricky in freemarker if we create one local variable as counter and manage it for last iteration.Luckily we have flag available in freemarker for checking the last iteration.So let's take look on that.
</li>
<li>item_index (deprecated by item?index): Index of current item in the loop.
</li>
<li>item_has_next (deprecated by item?has_next): Boolean value that tells if the current item is the last in the sequence or not.</li><br/> <br/>
<img src="https://i.pinimg.com/564x/99/79/47/99794790a2f04a1c8483fe5b932675df.jpg" style="display:none;height:250px;width:1360px;" />
</div>
<div class="blogger-post-footer">https://scontent-b-mxp.xx.fbcdn.net/hphotos-xap1/v/t1.0-9/10675541_896261013719814_5601513019470361090_n.jpg?oh=741b05a81becaae8bce36db141948a4a&oe=5531762A</div>Krutik Jayswalhttp://www.blogger.com/profile/16691396948811505379noreply@blogger.com0tag:blogger.com,1999:blog-2571457445842624811.post-20872250472714255442017-07-05T08:13:00.003-07:002020-02-06T22:54:04.627-08:00Alfresco Webscript : Export Data In Excel<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
There has been always requirement in one or another way to export data in excel or CSV. There are many developers who are find difficulties in developing a feature like this.<a href="https://github.com/Gagravarr?tab=overview&from=2017-06-01&to=2017-06-30&utf8=%E2%9C%93">Gagravarr </a>has given a very good example on exporting datalist in to an excel file.Main files which are responsible for downloading excel file and generating data are on <a href="https://github.com/Gagravarr/AlfrescoDataListDownload/tree/master/src/main/java/com/quanticate/opensource/datalistdownload">git</a>. One problem in this code is that parent webscript class is DeclarativeWebscript. This shouldn't have been used as in this kind of webscript controlling the response becomes more complicated. In the code written by <a href="https://github.com/Gagravarr?tab=overview&from=2017-06-01&to=2017-06-30&utf8=%E2%9C%93">Gagravarr </a>, controlling the response type is implemented by overriding methods named as <i>createTemplateParameters </i>and creating a new subclass named as WriteExcel and putting object of a WriteExcel class in model variable and finally it calls the <i>write</i> method of WriteExcel class from the response templete(freemarker).<br />
<br />
We can definitely customize this for any kind of data which we want to export in excel file.The main issue with this code is , its too complicated to understand,So i finally decided to create a simpler version of it for those who are starting up with alfresco.In real time scenario I have taken a reference from code written by <a href="https://github.com/Gagravarr?tab=overview&from=2017-06-01&to=2017-06-30&utf8=%E2%9C%93">Gagravarr </a>, as I am able to fully understood it.<br />
<br />
So let us begin on how we can export any alfresco data in a excel spreadsheet.</div>
<br />
<a href="https://lh3.googleusercontent.com/-LynjeHDn2Tg/WVy5tdVtesI/AAAAAAAAZfc/I1aNklhwwaUMcpIYCykOf9K9OxKzu3YsgCK4BGAYYCw/s1600/Export%2BTo%2BExcel.png" imageanchor="1"><img border="0" src="https://lh3.googleusercontent.com/-LynjeHDn2Tg/WVy5tdVtesI/AAAAAAAAZfc/I1aNklhwwaUMcpIYCykOf9K9OxKzu3YsgCK4BGAYYCw/s1600/Export%2BTo%2BExcel.png" /></a><br />
<br />
For exporting data in excel there no special case.The only artifact which we need to consider is java backed webscript. So let's begin with same.<br />
<br />
As usual we will be needing one descriptor file.<br />
<br />
<pre class="brush: xml" name="xml"><webscript>
<shortname>Export to Excel Webscript</shortname>
<description>Sample Export to excel webscript</description>
<url>/export/excel/</url>
<format default="xls">argument</format>
<authentication>user</authentication>
<transaction allow="readonly">required</transaction>
</webscript>
</pre>
<br />
Now we need to create one spring bean for java baked webscript.<br />
<pre class="brush: xml" name="xml"><bean class="com.export.ExportDataToExcel" id="webscript.com.export.export-excel.get" parent="webscript.org.alfresco.slingshot.datalists.list.get">
<!-- Inject services as per requirement -->
</bean>
</pre>
<br />
Java File For Exporting Data
<br />
<pre class="brush :java" name="java">package com.export;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.alfresco.repo.content.MimetypeMap;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.extensions.webscripts.AbstractWebScript;
import org.springframework.extensions.webscripts.WebScriptRequest;
import org.springframework.extensions.webscripts.WebScriptResponse;
public class ExportDataToExcel extends AbstractWebScript {
private String fileName = "ExcelSheet";
private String format = "xlsx";
/**
* This method is inherited from AbstractWebscript class and called
* internally.
*/
@Override
public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException {
writeDataInExcel(res);
}
/**
*
* @param res
* Used for controlling the response.In our case we want to give
* file as response.
* @param data
* Content which we need to write in excel file
* @throws IOException
*/
public void ResponseDataInExcel(WebScriptResponse res, byte[] data) throws IOException {
String filename = this.fileName + "." + this.format;
// Set Header for downloading file.
res.addHeader("Content-Disposition", "attachment; filename=" + filename);
// Set spredsheet data
byte[] spreadsheet = null;
res.setContentType(MimetypeMap.MIMETYPE_OPENXML_SPREADSHEET);
res.getOutputStream().write(data);
}
/**
*
* @return List of header which we need to write in excel
*/
public List<String> getHeaderList() {
List<String> listString = new ArrayList<>();
listString.add("Header1");
listString.add("Header2");
listString.add("Header3");
listString.add("Header4");
return listString;
}
/**
* This method is used for creating multiple row.So the inner list object
* will contain the cell details and the outer one will contain row details
*
* @return List of values which we need to write in excel
*/
public List<List<Object>> getData() {
List<List<Object>> listString = new ArrayList<>();
// Adding sample data
// ******************
// Creating sample Row 1
List<Object> sampleRow1 = new ArrayList<>();
sampleRow1.add("sampleCell11");
sampleRow1.add("sampleCell12");
sampleRow1.add("sampleCell13");
sampleRow1.add("sampleCell14");
// Creating sample Row 2
List<Object> sampleRow2 = new ArrayList<>();
sampleRow2.add(new Employee("Jhon"));
sampleRow2.add(new Employee("Ethan"));
sampleRow2.add(new Employee("Kevin"));
sampleRow2.add(new Employee("Mike"));
// Adding sample row in row list
listString.add(sampleRow1);
listString.add(sampleRow2);
return listString;
}
/**
*
* This method is used for Writing data in byte array.It is calling other
* methods as well which will help to generate data.
*
* @param res
* Writing content in output stream
* @throws IOException
*/
public void writeDataInExcel(WebScriptResponse res) throws IOException {
// Create Work Book and WorkSheet
Workbook wb = new XSSFWorkbook();
Sheet sheet = wb.createSheet("ExcelFile");
sheet.createFreezePane(0, 1);
generateHeaderInExcel(sheet);
generateDataInExcel(sheet);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
wb.write(baos);
ResponseDataInExcel(res, baos.toByteArray());
}
/**
* Used for generating header in excel.
*
* @param sheet
* It is an excel sheet object, where the header will be created
*/
public void generateHeaderInExcel(Sheet sheet) {
List<String> headerValues = getHeaderList();
Row hr = sheet.createRow(0);
for (int i = 0; i < headerValues.size(); i++) {
Cell c = hr.createCell(i);
c.setCellValue(headerValues.get(i));
}
}
/**
* Used for generating data in excel sheet
*
* @param sheet
* sheet It is an excel sheet object, where the data will be
* written
*/
public void generateDataInExcel(Sheet sheet) {
List<List<Object>> listOfData = getData();
// Give first row as 1 and column as 0
int rowNum = 1, colNum = 0;
for (List<Object> rowValues : listOfData) {
Row r = sheet.createRow(rowNum);
colNum = 0;
for (Object obj : rowValues) {
Cell c = r.createCell(colNum);
// Here you can add n number of condition for identifying the
// type of object and based on that fetch value of it
if (obj instanceof String) {
c.setCellValue(obj.toString());
} else if (obj instanceof Employee) {
c.setCellValue(((Employee) obj).getName());
}
colNum++;
}
rowNum++;
}
}
}
</pre>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Now let's understand few of the things from above code and how to customize it.I have added comments on method, they are well explanatory.There are few things which I would like to explain further more on this.So let's begin on that.</div>
<br />
<br />
<ul style="text-align: left;">
<li>You can update header values from <i>generateHeaderInExcel</i> function.</li>
<li>Use spring injection to use alfresco services.</li>
<li>For adding your data , you can write your own logic in <i>generateDataInExcel </i>function.Required parameters can be passed here.For an example if you want to get details of node, then you can write one function which will return list of nodes and useing nodeService, fetch details and set to to the excel cell</li>
<li>Excel file is created using apache poi api. You can use this API for any kind of formatting. There is a very good example explained in <a href="https://poi.apache.org/spreadsheet/quick-guide.html">this link</a></li>
</ul>
<div>
<br /></div>
<div>
<br /></div>
<div>
<b><u><span style="color: #351c75;">Action For Exporting Children Details in Excel</span></u></b><br />
<br /></div>
<div>
We have seen generic example on how we can export data in excel from alfresco using webscript. Now let's add some real time example in it. We will add one custom action in alfresco share on folder named as <b>Export Data.</b> What this action will do is that it will export all the data of its children in excel file.Exported excel file will have only few common properties in it like Name, Title , Created Date etc..</div>
<div>
<br /></div>
<div>
<div style="text-align: justify;">
For adding action on share side you can refer <a href="http://www.krutikjayswal.com/2016/08/custom-action-in-share-documentlibrary.html">Share DocumentLibrary Action</a> blog for more details.For adding custom action you need to follow below steps.</div>
</div>
<div>
<br />
<div style="text-align: justify;">
There are multiple ways of adding custom action in share, you can add it in share-config-custom.xml or as a new approach you can add xml file inside <i style="text-decoration-line: underline;">site-data/extension.</i> We will go by second approach.</div>
</div>
<div>
<br /></div>
<pre class="brush: xml" name="xml"><extension>
<modules>
<module>
<id>Export Action On Folders</id>
<version>1.0</version>
<auto-deploy>true</auto-deploy>
<configurations>
<config condition="DocLibCustom" evaluator="string-compare">
<dependencies>
<js src="Share-ExportToExcel/export-doclib-actions.js">
</js></dependencies>
</config>
<config condition="DocLibActions" evaluator="string-compare">
<actions>
<action icon="export-data" id="document-data-export" label="actions.document.export" type="javascript">
<param name="function" />onActionExportData
<evaluator>evaluator.doclib.action.isFolderType</evaluator>
</action>
</actions>
<actiongroups>
<actiongroup id="folder-browse">
<action id="document-data-export" index="101">
</action></actiongroup>
<actiongroup id="folder-details">
<action id="document-data-export" index="101">
</action></actiongroup>
</actiongroups>
</config>
</configurations>
</module>
</modules>
</extension>
</pre>
<div>
<br /></div>
In above code there are few things two consider, First one is custom action which we have added, custom action is type of javascript action, so we have specified function name as argument.Now this javascript function need to be defined in some javascript file, because of this reason only we have included a file called <b>export-doclib-actions.js</b>. Content of this file are as below.<br />
<br />
<br />
<pre class="brush: javascript" name="javascript">(function() {
YAHOO.Bubbling.fire("registerAction", {
actionName : "onActionExportData",
fn : function com_pdf_flipview_onActionExportData(file) {
window.location.href = Alfresco.constants.PROXY_URI+"export/excel/?nodeRef="+file.nodeRef;
}
});
})();
</pre>
<br />
<br />
If you see function, there is an argument called file.This is an javascript object , which has the data related to node on which the action is performed.As we will need nodeRef of folder, we will pass it as argument to repository webscript.<br />
<br />
Now let's make required changes in webscript.As we need to fetch properties from node we need to inject <i>nodeService</i> in webscript.For that we need to update bean definition as below.<br />
<br />
<br />
<pre class="brush: xml" name="xml"><bean class="com.export.ExportDataToExcel" id="webscript.com.export.export-excel.get" parent="webscript">
<property name="nodeService" ref="nodeService">
</property></bean></pre>
<br />
<br />
Apart from this there are few function which we need to update.The first one is <u><i>execute(WebScriptRequest req, WebScriptResponse res)</i></u><i>,</i>In this function we need to fetch the nodeRef which is passed from client side and send it to another function , for using it for future purpose.<br />
<br />
<br />
<pre class="brush: java" name="java">@Override
public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException {
String nodeRefParam=req.getParameter("nodeRef");
if(nodeRefParam!=null){
writeDataInExcel(res,new NodeRef(nodeRefParam));
}
}
</pre>
<br />
Second function which we need to update is <i>getHeaderList </i>This function includes the details of header.We need to add list of column name which we need to populate.<br />
<pre class="brush: java" name="java">public List<string> getHeaderList() {
List<string> listString = new ArrayList<>();
listString.add("Name");
listString.add("Title");
listString.add("Description");
listString.add("Created Date");
return listString;
}</string></string></pre>
<div style="text-align: justify;">
Third function which we need to update is <i>generateDataInExcel</i>,In this we need to include an argument folder node and pass it in to <i>getData </i>function.One more change in this function which we need to do it handling the Date object, there things which we need to export are of string type those are already handled in this function.We need to handle an date object here.Function will be updated like below for that.</div>
<br />
<pre class="brush :java" name="java">public void generateDataInExcel(Sheet sheet,NodeRef folderNode) {
List<List<Object>> listOfData = getData(folderNode);
// Give first row as 1 and column as 0
int rowNum = 1, colNum = 0;
for (List<Object> rowValues : listOfData) {
Row r = sheet.createRow(rowNum);
colNum = 0;
for (Object obj : rowValues) {
Cell c = r.createCell(colNum);
// Here you can add n number of condition for identifying the
// type of object and based on that fetch value of it
if (obj instanceof String) {
c.setCellValue(obj.toString());
} else if (obj instanceof Employee) {
c.setCellValue(((Employee) obj).getName());
} else if (obj instanceof Date) {
c.setCellValue(obj.toString());
}
colNum++;
}
rowNum++;
}
}
</pre>
<br />
Now in <i>getData </i>function, we need to get actual data from children and return an list of it.Code should be updated for that function like below.<br />
<br />
<pre class="brush :java" name="java">public List<List<Object>> getData(NodeRef folderNode) {
List<List<Object>> listData = new ArrayList<>();
List<ChildAssociationRef> childAssociationRefList=nodeService.getChildAssocs(folderNode);
for(ChildAssociationRef child:childAssociationRefList){
List<Object> row = new ArrayList<>();
row.add(nodeService.getProperty(child.getChildRef(),ContentModel.PROP_NAME));
row.add(nodeService.getProperty(child.getChildRef(),ContentModel.PROP_TITLE));
row.add(nodeService.getProperty(child.getChildRef(),ContentModel.PROP_DESCRIPTION));
row.add(nodeService.getProperty(child.getChildRef(),ContentModel.PROP_CREATED));
listData.add(row);
}
return listData;
}</pre>
<br />
Once all above things are done , you will find an action on foldernamed as <b>Export Data</b>, on click of it , it will export data of its children in excel.<br />
<br />
Github link for above example is <a href="https://github.com/krutik-jayswal/Export-To-Excel">here.</a></div>
<div class="blogger-post-footer">https://scontent-b-mxp.xx.fbcdn.net/hphotos-xap1/v/t1.0-9/10675541_896261013719814_5601513019470361090_n.jpg?oh=741b05a81becaae8bce36db141948a4a&oe=5531762A</div>Krutik Jayswalhttp://www.blogger.com/profile/16691396948811505379noreply@blogger.com8tag:blogger.com,1999:blog-2571457445842624811.post-33858466242499290322017-04-28T00:43:00.001-07:002020-02-06T22:52:26.279-08:00Alfresco SDK 3.0<div dir="ltr" style="text-align: left;" trbidi="on">
Its been only just few days ,that alfresco SDK 3.0 has been released.There are few amazing changes on alfresco SDK and restructuring on resources.<br />
<br />
After a little analysis on the same i found few important things on Alfresco SDK 3.0.0.<br />
<br />
<br />
<ul style="text-align: left;">
<li style="text-align: justify;">In SDK 3.0 , there are not much more confrontational change for changing the database provider. There are few attributes defined in POM.xml. For each database provider like for H2 we need to set <enableH2> as true, for MySQL its <enableMySQL>. This attributes are defined under Configuration section of org.alfresco.maven.plugin plugin. For each configuration there are different properties file defined.See below image for the same. In the alfresco-global-enterprise.properties file SQLServer is configured.</li>
</ul>
<br />
<br />
<a href="https://lh3.googleusercontent.com/-g2xJjFNlIFY/WQL1Q-_PRFI/AAAAAAAAZcE/DXu9-WaBbMouInnLCwQnnVVBI6MgFGCdwCK4B/s1600/database-properties.png" imageanchor="1" style="font-family: "times new roman", serif; font-size: 18.6667px; text-align: justify;"><img border="0" src="https://lh3.googleusercontent.com/-g2xJjFNlIFY/WQL1Q-_PRFI/AAAAAAAAZcE/DXu9-WaBbMouInnLCwQnnVVBI6MgFGCdwCK4B/s1600/database-properties.png" /></a><br />
<br />
<br />
<ul style="text-align: left;">
<li style="text-align: justify;">Second biggest change is moving of client side resources on share side in to the "\src\main\resources\META-INF\resources" folder. So all your JavaScript, CSS and other resources will be in this place, including your AIKAU widget.</li>
<li style="text-align: justify;">From now onwards, running an alfresco or share project will not require any profile to run the alfresco/share tomcat. Instead you need to specify argument as "alfresco:run" in both the project. Please read it carefully alfresco:run is not an maven profile. It’s just an argument.</li>
<li style="text-align: justify;">Hot deployment capabilities are much better now. Though we still need to add hotswap java agent for webscript refresh configuration. It is strange that for java hot deployment there is nothing to configure.</li>
<li style="text-align: justify;">I am still facing issues on hot reloading of client side resources. This is worst thing, i hope there will be something for the same. Still didn't figure out any solution.</li>
<li style="text-align: justify;">If an AMP deployment was a headache for you, than SDK 3.0 is having solution. It is providing a jar based deployment. You just need to create Jar archetype project and then you are ready for the jar deployment. Its been a great change I must say. It will help in many things. In terms of deployment and all.</li>
<li style="text-align: justify;">Till now I have just found this few things. I will keep this blog updated. For the changes which I found in Alfresco SDK 3.0.</li>
</ul>
<br />
<br />
<br />
Hope this helps :).</div>
<div class="blogger-post-footer">https://scontent-b-mxp.xx.fbcdn.net/hphotos-xap1/v/t1.0-9/10675541_896261013719814_5601513019470361090_n.jpg?oh=741b05a81becaae8bce36db141948a4a&oe=5531762A</div>Krutik Jayswalhttp://www.blogger.com/profile/16691396948811505379noreply@blogger.com0tag:blogger.com,1999:blog-2571457445842624811.post-889890075324946132016-10-04T00:13:00.003-07:002016-10-13T11:44:19.799-07:00Repository webscript in alfresco<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
<div dir="ltr" style="text-align: justify;" trbidi="on">
<h3 class="topic-heading">
Introduction to webscript
</h3>
<div style="text-align: justify;">
Web script is backbone in alfresco. Most of the things in alfresco is built using webscript only. Whether we talk about the user interface or the backend services in alfresco. From the 5th version onwards alfresco introduced AIKAU, in which they have changed few things in terms of implementation of webscript on share side.Old way of creating webscript will remain as it is.On previous versions, alfresco was using surf framework for webscript.They have added few more libraries in aikau for webscript.
</div>
<br />
<br />
<br />
<h3 class="topic-heading">
<b>Architecture of webscript</b>
</h3>
Lets have a look on webscript architecture of alfresco.Webscript follows MVC architecture only.<br />
<br />
<br />
<a href="http://2.bp.blogspot.com/-N510i-pe7O0/V9-V5qAOfdI/AAAAAAAATi0/nhIP825ybwgHa5gjD6Pv24GMeqgG1NrvQCK4B/s1600/Architecture%2Bof%2BWebscripts.jpg" imageanchor="1"><img alt="Architecture of webscripts" border="0" height="568" src="https://2.bp.blogspot.com/-N510i-pe7O0/V9-V5qAOfdI/AAAAAAAATi0/nhIP825ybwgHa5gjD6Pv24GMeqgG1NrvQCK4B/s640/Architecture%2Bof%2BWebscripts.jpg" title="Architecture of webscripts" width="640" /></a>
<br />
<br />
There are three phases in MVC design pattern. Request , Controller and Response. Same is the case with webscript. Using Uri request will come to webscript, which will be followed to controller controller will deal with services and finally it will give the response in desired format.<br />
<br />
Lets talk on each of this component.<br />
<br />
Request Uri of alfresco webscript is defined in descriptor file of alfresco.In descriptor file you can define arguments which are going to be passed in uri.<br />
<br />
In webscript, there can be 2 types of controller.Either it will be a java controller or it will be a javascript controller. Java script controller is having access of limited services, while using java you will be having access of all services which alfresco provides.Depends on the requirement you can choose the controller.<br />
<br />
Response of webscript can be of any type, it can be HTML, JSON, XML or any thing else.<br />
<br />
<br />
<h3 class="topic-heading">
<b>Types of webscript</b>
</h3>
We talked about architecture of webscript , now lets talk about the types of webscript available in alfresco.Basically there are 2 types of webscript in alfresco.<br />
<br />
1. Data Webscript<br />
<br />
Data webscript are responsible for dealing with data only.This kind of webscript will be created at alfresco end.For an example, suppose we want to retrieve data of invoice type of document, which will include metadata like Invoice Number, creation date , amount etc..In that case we will create data webscript and will return response in required format.<br />
<br />
<br />
2. Presentation webscript<br />
<br />
Presentation webscript are dealing with the presentation layer of alfresco.This kind of webscript are mostly created at share.On previous version of alfresco there was alfresco client so on those version we can have presentation webscript on alfresco end as well, but in the latest version there is there is no alfresco ui client so , presentation webscripts are created at share end only. Dashlet is one of the best example of presentation webscript.<br />
<br />
<h3 class="topic-heading">
<b>Implementation of webscript using javascript</b>
</h3>
<b><br /></b>There are 2 ways in which we can access repository services in alfresco.First is using <i>Java backed webscripts</i><b> </b>another is <i>Javascript backed webscript</i>. As i mentioned earlier, java backed webscripts are having more control over services compare to javascript backed webscript.We will talk on both the way of implementation webscript.Let's start with the javascript backed webscript.<br />
<br />
Let's talk about deployment, there are few ways using which we can deploy webscript in alfresco (if it is alfresco repository webscript). The places where we can place the alfresco webscript and in which order it will go for finding the webscript are as below.<br />
<br />
Repository folder : /Company Home/Data Dictionary/Web Scripts Extensions<br />
Repository folder : /Company Home/Data Dictionary/Web Scripts<br />
Class path folder : /alfresco/extension/templates/webscripts<br />
<br />
There are few limitation for webscript when we are deploying it inside repository folder.For example java backed webscript will not be possible in that case.If we are developing it using class path all things will be possible. Let's take a look on each and every component of webscript with small example of it.<br />
<br />
<dl>
<dt>Webscript Descriptor</dt>
<dd>Webscript descriptor file is XML file, which includes the webscript configuration elements.This elements defines the mod in which execution will happen, default response template, parameters of webscript, family of webscript etc...Naming convention of webscript descriptor files is also important.It should be named as <i>NameOf Webscript(.)MethodName(.)desc(.)xml.</i> Method can be given as GET, POST, PUT, DELETE etc..Below is one sample webscript descriptor file.<br />
<pre class="brush: xml" name="xml"><webscript>
<shortname>Group Member Listing</shortname>
<url>/groupmember/list</url>
<format default="html">argument</format>
<authentication>none</authentication>
<transaction>required</transaction>
</webscript>
</pre>
<br />
There are few other elements as well which we can define in webscript descriptor.This webscript descriptor is repository side webscript.All the element of alfresco repository side webscript are very well explained in <a href="http://docs.alfresco.com/5.0/references/api-wsdl-webscript-descriptor-language-reference.html">Webscript Descriptor Documentation</a> link.
</dd>
<dt>Webscript Controller</dt>
<dd>In case of javascript backed webscript, javascript filename will be like <i>NameOf Webscript(.)MethodName(.)js. </i>This file<i> </i>will behave as webscript controller.Javascript backed webscript is having limitation on services as its mentioned earlier.You can take a look on few of javascript api on <a href="https://community.alfresco.com/docs/DOC-6069-40-javascript-api">Alfrescp Javascript API</a> link. If business requirement of webscript is not much more complex and it can be achievable using services which javascript api provides in that case we can use that.In case of java backed webscript few we are having full access of services which alfresco provides. All services on java side are very well explained on <a href="http://docs.alfresco.com/5.1/concepts/dev-services.html">Foundation API</a> link.Let's take a look on one example of javascript which saves list of users from administrator group in model variable.<br />
<pre class="brush: javascript" name="javascript">var node = people.getGroup("GROUP_ALFRESCO_ADMINISTRATORS");
if(node){
model.members = people.getMembers(node);
}
</pre>
</dd>
<dt>Webscript Response Template</dt>
<dd>Webscript Response template can be of html, json, xml, atom, rss or text type.This response format can be specified in url as argument like <b>?format=html </b> if no format is specified in url that case default format which is specified in descriptor file of webscript will be taken.If in descriptor file as well there is no format specified than html will be taken as default response template.For each type of response template new file is create.For example for html response file name will be like WebscriptFileName.get.html.ftl, for xml file name it will be like WebscriptFileName.get.xml.ftl etc..ftl stands for freemarker.Response template in alfresco are written in freemarker template engine.
Let's take an previous example which was saving list of admin group users in model variable, from template engine we will print those values.
<br />
<pre class="brush: java" name="java">{
"users":[
<#list members as person>
"${person.properties.userName}"
</#list>
]
}
</pre>
</dd>
<dt>Webscript Configuration</dt>
<dd>This file is optional file.Its XML file and contains configuration values.Lets take a look on below code , which is written in alfresco javascript for reading config file.
<br />
<b>Javascript Code</b>
<br />
<pre class="brush: javascript" name="javascript">var xmlElements = new XML(config.script);
model.value1 = xmlElements.prop1;
model.value2 = xmlElements.prop2;
</pre>
<br />
<b>XML configuration file</b>
<br />
<pre class="brush: xml" name="xml"> <webscriptname>
<prop1>hello</prop1>
<prop2>userName</prop2>
</webscriptname>
</pre>
</dd>
<dt>Webscript Locale Bundle</dt>
<dd>This file is an optional file.It is used for achieving Internationalization in webscript.This is nothing but a property file.There will be multiple properties file ,each file will be having its own locale for representing language, for example if we say english in that case the file name will be like webscript_id.methodname._locale.properties.For each locale there will be a new property file.For an example if in above, group member webscript, we want to retrieve "Users" constant from properties file than you can define properties file and display it.Take a look on below files which are changed.<br />
<b>Properties File</b><br />
<pre class="brush: java" name="java">users = Users in Admin Group
</pre>
<br />
<br />
<b>Response Template</b><br />
<pre class="brush: java" name="java">{
" ${msg("users")}":[
<#list members as person>
"${person.properties.userName}"
</#list>
]
}
</pre>
<br /></dd>
</dl>
<br />
<h3 class="topic-heading">
<b>Implementation of java backed webscript</b>
</h3>
Java backed webscript have wide range of services which can be used while development compare to javascript backed webscript.In the previous version of alfresco hot reloading was really big issue when we work with java classes in alfresco, but from the 5th version onward hot reloading of java is supported.It was really a great enhancement made by alfresco, though hot reloading of XML file is still not possible.<br />
<br />
For using java backed webscript, java class which we are going to create must extend either DeclarativeWebScript or AbstractWebScript Class.Both of them can be used depend on the scenario.DeclarativeWebScript class does not have full control over response, while AbstractWebScript have full control over the response.<br />
<br />
Let's an example of two different business scenarios.In First case we need to create webscript which will export data list of alfresco site in excel sheet.In this case we can extend AbstractWebScript class for webscript implementation.In other case we need to retrieve all data list which are created in site.In this case we can extend DeclarativeWebScript class for webscript implementation.<br />
<br />
Now we will take a look on implementation of java backed webscript. Few things in terms of implementation will remain as it is , which were there in javascript backed webscript implementation.Things which will remain as it is are response template and descriptor file. As it will be java controller there is no need of javascript controller.<br />
<br />
For using this java class we need to inject bean inside context file in alfresco.If we are using maven architecture than we should put this bean inside <i>webscript-context.xml. </i>For java backed webscript naming convention of bean id is really important, as based on the bean id only it is going to find the webscript location.Bean id must follow below rules.<br />
<br />
<ul>
<li>Bean id must start with <i>webscript</i>prefix.Using that only alfresco engine identifies that it is an webscript.</li>
<li>Bean id must end with the HTTP method.</li>
<li>In between this 2 prefix and suffix , you have to add webscript package including name of webscript.</li>
</ul>
<br />
Consider an example of java backed webscript which will save a list of nodes with properties in model and freemarker will print those things in json.We will need to pass one NodeRef as argument.From that noderef we will retrieve its children and it will display its children with few properties of it.<br />
<dl>
<dt>Webscript Descriptor</dt>
<dd>There will be no change in descriptor file if we compare it with the javascript backed webscript.But few of the element may affect the accessibility of services.For an example authentication tag of webscript descriptor.If we keep this as none, services which required authentication will not be accessible.<br />
<pre class="brush: xml" name="xml"><webscript>
<shortname>Node with few properties</shortname>
<url>/list/properties</url>
<format default="json">argument</format>
<authentication>user</authentication>
<transaction>required</transaction>
</webscript>
</pre>
<br /></dd>
<dt>Response Template</dt>
<dd>As we required output in json and out default out put format in webscript descriptor is json.We will create response template with the name of <i>nodelist.get.json.ftl</i>.Java controller will return object of map in which there will be 2 properties name and title of node.In this freemarker file , we have to iterate map object and print values in json. Below is code for same.
<br />
<pre class="brush: xml" name="xml">
{
"data":[
<#list list?values as node>
{
<#list node?keys as prop>
"${prop}" :"${node[prop]}"
<#if prop_has_next>,</#if>
</#list>
}<#if node_has_next>,</#if>
</#list>
]
}
</pre>
<br /></dd>
<dt>Java Controller</dt>
<dd>As we do not need to change the response format, we will extend DeclarativeWebScript class and will create java controller out of it.We will also create one spring bean inside webscript-context.xml file, which will refer this java class.In this classs we will require nodeService of alfresco foundation api, for iterating retrieval of children and properties of it and than saving it in map.
<br />
<pre class="brush: java" name="java">
package com.sample;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.springframework.extensions.webscripts.Cache;
import org.springframework.extensions.webscripts.DeclarativeWebScript;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptRequest;
public class ListNodeWebScript extends DeclarativeWebScript {
private NodeService nodeService;
public NodeService getNodeService() {
return nodeService;
}
public void setNodeService(NodeService nodeService) {
this.nodeService = nodeService;
}
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status, Cache cache) {
Map<String, Object> model = new HashMap<String, Object>();
Map<String, Object> childrens = new HashMap<String, Object>();
NodeRef nodeRef = new NodeRef(req.getParameter("nodeRef"));
List<ChildAssociationRef> childAssocList = nodeService.getChildAssocs(nodeRef);
for (ChildAssociationRef child : childAssocList) {
Map<String, Object> nodes = new HashMap<String, Object>();
nodes.put("Name", nodeService.getProperty(child.getChildRef(), ContentModel.PROP_NAME));
nodes.put("Title", nodeService.getProperty(child.getChildRef(), ContentModel.PROP_TITLE));
childrens.put(child.getChildRef().getId(), nodes);
}
model.put("list", childrens);
return model;
}
}
</pre>
<br /></dd>
<dt>Webscript Context(Injecting webscript bean)</dt>
<dd>In spring bean context file we will inject few services which we are going to use in JavaController. All the foundation api you can use here,apart from that if you have defined your own services those will also be accessible here.While using services make sure you are using safely.You can refer <a href="https://alfrescoshare.wordpress.com/tag/security/">how to safely call java services ?</a> blog for more details.
<br />
<pre class="brush: xml" name="xml">
<beans>
<bean class="com.sample.ListNodeWebScript" id="webscript.com.sample.listnode.get" parent="webscript">
<property name="nodeService" ref="nodeService"></property>
</bean>
</beans>
</pre>
<br /></dd>
</dl>
</div>
</div>
<style>
h1,dl,dt,dd,p,a {
margin: 0;
padding: 0;
}
/* ---- Page structure ---- */
#beers {
width: 500px;
padding: 20px;
margin: auto;
background: #eeebe3;
border: 5px solid #5a523d;
text-align: left;
}
/* ---- Type ---- */
h1 {
text-align: center;
color: #3d3111;
margin-bottom: 20px;
}
.topic-heading{
font-size: 15px!important;
text-transform: uppercase!important;
font-weight: 600!important;
color: #434343!important;
text-decoration: underline!important;
}
p {
font: 16px/1.3 "Delicious-Bold", "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, sans-serif;
}
/* ---- Definition list ---- */
dl {
margin-bottom: 20px;
}
dt {
text-shadow: rgba(255, 255, 255, .8) 2px 2px 0;
color: #822020;
margin-bottom: 0px;
border: 1px solid black;
padding-left: 10px;
}
dd {
text-shadow: rgba(255, 255, 255, .5) 1px 1px 0;
padding: 10px;
border-width: 20px;
-moz-border-image: url(bubble.png) 20 stretch;
-webkit-border-image: url(bubble.png) 20 stretch;
-o-border-image: url(bubble.png) 20 stretch;
-khtml-border-image: url(bubble.png) 20 stretch;
border-image: url(bubble.png) 20 stretch;
border: 1px solid black;
margin-bottom: 20px;
}
p {
text-align: justify;
}
</style>
</div>
<div class="blogger-post-footer">https://scontent-b-mxp.xx.fbcdn.net/hphotos-xap1/v/t1.0-9/10675541_896261013719814_5601513019470361090_n.jpg?oh=741b05a81becaae8bce36db141948a4a&oe=5531762A</div>Krutik Jayswalhttp://www.blogger.com/profile/16691396948811505379noreply@blogger.comtag:blogger.com,1999:blog-2571457445842624811.post-33646257770198017822016-08-27T06:09:00.000-07:002016-08-27T06:09:18.897-07:00Evaluators in alfresco share<div dir="ltr" style="text-align: left;" trbidi="on">
Evaluators are used for control visibility of share document library action.For creating custom action in alfresco share you can follow below link.It has most of the things covered.<br />
<br />
<a href="http://www.krutikjayswal.com/2016/08/custom-action-in-share-documentlibrary.html">http://www.krutikjayswal.com/2016/08/custom-action-in-share-documentlibrary.html</a><br />
<br />
Evaluators are nothing but a spring bean which is used for evaluating the visibility of custom action in alfresco share.In alfresco there are already few predefined evaluators are there.Those are generic and can me used in multiple scenarios.On below link all those evaluators are very well explained.<br />
<br />
<a href="http://docs.alfresco.com/5.1/concepts/doclib-predefined-evaluators-reference.html">http://docs.alfresco.com/5.1/concepts/doclib-predefined-evaluators-reference.html</a><br />
<br />
Even if all those evaluators are there, there can be a business requirement of creating a custom evaluator.In custom evaluators there are few things using which you can do evaluation like properties of node.<br />
<br />
Lets take one example of custom evaluator.<br />
In my previous blog we have created action called "open-form" and have added it on document-browse,document-details,folder-browse and folder-details section.
<br />
<pre class="brush: java" name="xml"><action id="open-form" label="actions.open.form" type="javascript">
<param name="function" />onActionFormDialog
<param name="itemKind" />action
<param name="itemId" />script
<param name="mode" />create
<param name="destination" />{node.nodeRef}
<param name="successMessage" />message.execute-script.success
<param name="failureMessage" />message.execute-script.failure
</action>
</pre>
<br />
<br />
Now for adding evaluator you have to create bean in slingshot application context file.That bean will reference a java class which extends a class called <span style="font-family: "courier new" , monospace; font-size: 14.4px; font-weight: bold; white-space: nowrap;">org.alfresco.web.evaluator.BaseEvaluator</span>.Lets take a loon on that java file.<br />
<br />
SampleEvaluator.Java<br />
<br />
<pre class="brush: java" name="java">import org.alfresco.web.evaluator.BaseEvaluator;
import org.json.simple.JSONObject;
public class SampleEvaluator extends BaseEvaluator{
@Override
public boolean evaluate(JSONObject jsonObject) {
boolean result=false;
//Evaluate
return result;
}
}
</pre>
<br />
In the method <i>public boolean evaluate(JSONObject jsonObject), </i>You can evaluate the node and set the value of result variable accordingly.Properties you can get from node are in jsonObject argument of method.Apart from this if you need anything else you can call alfresco webservice also.<br />
<br />
<pre class="brush: java" name="java">{
"node": {
"isLink": false,
"nodeRef": "workspace:\/\/SpacesStore\/43dd6777-b40f-4c49-9533-cd5a180fe4d4",
"permissions": {
"inherited": true,
"roles": ["ALLOWED;GROUP_EVERYONE;Contributor;INHERITED"],
"user": {
"Delete": true,
"Write": true,
"CancelCheckOut": false,
"ChangePermissions": true,
"CreateChildren": true,
"Unlock": false
}
},
"isLocked": false,
"aspects": ["cm:titled", "cm:auditable", "sys:referenceable", "sys:localized"],
"isContainer": true,
"type": "cm:folder",
"properties": {
"cm:title": "",
"cm:creator": {
"firstName": "Administrator",
"lastName": "",
"displayName": "Administrator",
"userName": "admin"
},
"cm:modifier": {
"firstName": "Administrator",
"lastName": "",
"displayName": "Administrator",
"userName": "admin"
},
"cm:created": {
"iso8601": "2016-08-27T12:56:35.349Z",
"value": "Sat Aug 27 18:26:35 IST 2016"
},
"cm:name": "Inv",
"sys:store-protocol": null,
"sys:node-dbid": null,
"sys:store-identifier": null,
"sys:locale": null,
"cm:modified": {
"iso8601": "2016-08-27T12:56:35.349Z",
"value": "Sat Aug 27 18:26:35 IST 2016"
},
"cm:description": "",
"sys:node-uuid": null
}
},
"webdavUrl": "\/webdav\/Shared\/Inv",
"parent": {
"isLink": false,
"nodeRef": "workspace:\/\/SpacesStore\/3372c9eb-8ea2-4b1f-a19c-386158313f8f",
"permissions": {
"inherited": false,
"roles": ["ALLOWED;GROUP_EVERYONE;Contributor;DIRECT"],
"user": {
"Delete": true,
"Write": true,
"CancelCheckOut": false,
"ChangePermissions": true,
"CreateChildren": true,
"Unlock": false
}
},
"isLocked": false,
"aspects": ["cm:titled", "cm:auditable", "sys:referenceable", "sys:localized", "app:uifacets"],
"isContainer": true,
"type": "cm:folder",
"properties": {
"cm:title": "Shared Folder",
"cm:creator": {
"firstName": "System",
"lastName": "User",
"displayName": "System User",
"userName": "System"
},
"cm:modifier": {
"firstName": "Administrator",
"lastName": "",
"displayName": "Administrator",
"userName": "admin"
},
"cm:created": {
"iso8601": "2016-08-23T11:50:00.399Z",
"value": "Tue Aug 23 17:20:00 IST 2016"
},
"sys:store-protocol": null,
"sys:store-identifier": null,
"cm:description": "Folder to store shared stuff ",
"sys:node-uuid": null,
"cm:name": "Shared",
"sys:node-dbid": null,
"sys:locale": null,
"cm:modified": {
"iso8601": "2016-08-27T12:56:35.402Z",
"value": "Sat Aug 27 18:26:35 IST 2016"
},
"app:icon": "space-icon-default"
}
},
"fileName": "Inv",
"nodeRef": "workspace:\/\/SpacesStore\/43dd6777-b40f-4c49-9533-cd5a180fe4d4",
"displayName": "Inv",
"location": {
"path": "\/Shared",
"parent": {},
"file": "Inv",
"repositoryId": "6c2cf525-c6bf-4e63-8f8e-71d15bf1a588",
"repoPath": "\/Shared"
},
"version": "1.0",
"likes": {
"isLiked": false,
"totalLikes": 0
}
}
</pre>
<br />
In slingshot application context file you have to create bean like below.<br />
<br />
<pre class="brush: java" name="java"> <bean class="com.evaluator.SampleEvaluator" id="evaluator.alferesco.sample">
</bean></pre>
</div>
<div class="blogger-post-footer">https://scontent-b-mxp.xx.fbcdn.net/hphotos-xap1/v/t1.0-9/10675541_896261013719814_5601513019470361090_n.jpg?oh=741b05a81becaae8bce36db141948a4a&oe=5531762A</div>Krutik Jayswalhttp://www.blogger.com/profile/16691396948811505379noreply@blogger.comtag:blogger.com,1999:blog-2571457445842624811.post-67161962943480541652016-08-26T11:49:00.002-07:002018-03-28T03:58:18.142-07:00Alfresco Certified Engineer<div dir="ltr" style="text-align: left;" trbidi="on">
Basic information on alfresco certification are available on below link.<br />
<br />
<a href="https://university.alfresco.com/ACE">https://university.alfresco.com/ACE</a><br />
<br />
<br />
<div style="text-align: justify;">
Getting alfresco certification is dream of each developer who works in alfresco.Clearing a certification will not be difficult for those who works in alfresco since long time or for those who are conceptually clear.For clearing alfresco certification I was reading alfresco docs and was performing practical things on which i was having doubts.The most difficult things which i faces on clearing the certification is getting the dumps like wise people are getting for java or any other technologies.This was the most difficult things which i faced while preparing for certification.As without dumps , getting a confidence of clearing certification is very difficult.</div>
<br />
<a href="https://i.pinimg.com/originals/77/e7/55/77e755dfe44864bea838fcb522d41891.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://i.pinimg.com/originals/77/e7/55/77e755dfe44864bea838fcb522d41891.jpg" style="-webkit-user-select: none;" /></a><br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
Few tips while preparing for alfresco certification.<br />
<br />
If you have friends who are working in alfresco, tell him to prepare list of questions and try to solve those like you are giving exam. Luckily I have few.<br />
<br />
As i said in the earlier para, do some practicals on which you are having doubt and don't waste your time on simple things.Read it and leave it if you know that.<br />
<br />
Few people might have concern on aikau as its the latest ui framework in alfresco, but believe me it is not the one which you should concentrate.For aikau it will be enough if you are completing tutorials on following link.<br />
<br />
<a href="https://github.com/Alfresco/Aikau/tree/master/tutorial/chapters">https://github.com/Alfresco/Aikau/tree/master/tutorial/chapters</a><br />
<br />
The other reason for not concentrating on it is , there are very less questions coming from aikau part.<br />
<br />
Regarding how does it feel of being certified, well for me its like getting gold medal in olympics.<br />
<br /></div>
<div class="blogger-post-footer">https://scontent-b-mxp.xx.fbcdn.net/hphotos-xap1/v/t1.0-9/10675541_896261013719814_5601513019470361090_n.jpg?oh=741b05a81becaae8bce36db141948a4a&oe=5531762A</div>Krutik Jayswalhttp://www.blogger.com/profile/16691396948811505379noreply@blogger.comAhmedabad, Gujarat, India23.022505 72.57136209999998822.7886785 72.248638599999992 23.256331499999998 72.894085599999983tag:blogger.com,1999:blog-2571457445842624811.post-13475128047402467462016-08-20T13:44:00.000-07:002016-08-27T03:42:35.403-07:00Custom action in share documentlibrary<div dir="ltr" style="text-align: left;" trbidi="on">
There are multiple types of action available in alfresco share which you can add in document library.Few examples are already available in internet for adding custom action in alfresco share.The most common exmaple is adding an action called send-as-email in document library.That exmaple is added in documentation of alfresco share as well.Take a look on below link for same.<br />
<br />
<a href="http://docs.alfresco.com/5.0/tasks/dev-extensions-share-tutorials-add-action-doclib.html">http://docs.alfresco.com/5.0/tasks/dev-extensions-share-tutorials-add-action-doclib.html</a><br />
<br />
There are multiple business cases in which you need to implement custom action in alfresco.This blog will give you description about what kind of things you can achieve in custom action of alfresco share.<br />
<br />
Below is screenshot of document details page on which custom actions are highlighted.<br />
<br />
<img height="233" src="https://docs.alfresco.com/sites/docs.alfresco.com/files/public/images/docs/default5_1/dev-extensions-share-doclib-document-actions.png" style="-webkit-user-select: none;" width="640" /><br />
<br />
<br />
There are few components which can be customized or used in alfresco for implementation of custom action in alfresco share.Those are as below.<br />
<br />
<b>Evaluator</b><br />
Using evaluator we can control the visibility/access of action for users.There are multiple parameters by which we can control the visibility. Evaluation of node can be done on aspects, properties state of node or the type of node.<br />
<br />
<b>Type of action</b><br />
There are multiple type of action you can create in share.All of them are as below.<br />
<br />
javascript<br />
With the use of this type of action you can call java script function.Lets take an example.Take a look on below code.<br />
<br />
<div class="p1">
<br /></div>
<pre class="brush: java" name="xml"><action id="open-form" label="actions.open.form" type="javascript">
<param name="function">onActionFormDialog</param>
<param name="itemKind">action</param>
<param name="itemId">script</param>
<param name="mode">create</param>
<param name="destination">{node.nodeRef}</param>
<param name="successMessage">message.execute-script.success</param>
<param name="failureMessage">message.execute-script.failure</param>
</action>
</pre>
<br />
If you take look on each param which is passed in function, than you will realize that all of those params are related to form.The parameter named function is used for identification for which function function is called. Rest of all params are used inside that function.There are some predifined javascript function which you can use.Please take a look on <i>actions.js</i> file in alfresco share for all function.If you are using this function, you have to create <i>action-executor</i> with the same id of action.<br />
<br />
page<br />
<br />
Redirection to internal application(Withinn pages of alfresco share)<br />
<br />
link<br />
Redirection to external web application, for example redirection to http://www.google.com<br />
Any of above action can be visible on any/all of the below section.<br />
<br />
<ol style="text-align: left;">
<li>Folder Details</li>
<li>Folder Browse</li>
<li>Document Details</li>
<li>Document Browse</li>
<li>Folder Link Browse</li>
<li>Folder Link Details</li>
<li>Document Link Browse</li>
<li>Document Link Details</li>
</ol>
<br />
<br />
Below is sample code for adding action on desired location.
<br />
<pre class="brush: java" name="xml">
<config condition="DocLibActions" evaluator="string-compare">
<actions>
<action id="open-form" label="actions.open.form" type="javascript">
<param name="function" />onActionFormDialog
<param name="itemKind" />action
<param name="itemId" />script
<param name="mode" />create
<param name="destination" />{node.nodeRef}
<param name="successMessage" />message.execute-script.success
<param name="failureMessage" />message.execute-script.failure
</action>
</actions>
<actiongroups>
<actiongroup id="document-browse">
<action id="open-form" index="400"></action>
</actiongroup>
<actiongroup id="document-details">
<action id="open-form" index="400"></action>
</actiongroup>
<actiongroup id="folder-details">
<action id="open-form" index="400"></action>
</actiongroup>
<actiongroup id="folder-browse">
<action id="open-form" index="400"></action>
</actiongroup>
</actiongroups>
</config>
</pre>
<br />
In above <i>index</i> attribute is index of action in the list of action.
</div>
<div class="blogger-post-footer">https://scontent-b-mxp.xx.fbcdn.net/hphotos-xap1/v/t1.0-9/10675541_896261013719814_5601513019470361090_n.jpg?oh=741b05a81becaae8bce36db141948a4a&oe=5531762A</div>Krutik Jayswalhttp://www.blogger.com/profile/16691396948811505379noreply@blogger.comtag:blogger.com,1999:blog-2571457445842624811.post-48133019596494090052016-07-22T06:40:00.002-07:002017-06-22T00:37:44.277-07:00OCR on pdf file in alfresco<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
There are lots of tool available which can be integrated with alfresco for performing PDF to PDF conversation with OCR.The best tool which i used so far is PDFsandwich.Any one can download it as its an open source.Another tool which can be integrated is tesseract.Internally pdfsandwich is using tesseract only, but i prefer pdfsandwich.</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://cdn.toptenreviews.com/rev/site/cms/category_headers/674-h_main-w.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="OCR in alfresco" border="0" src="http://cdn.toptenreviews.com/rev/site/cms/category_headers/674-h_main-w.png" style="-webkit-user-select: none;" title="OCR in alfresco" /></a></div>
<br />
<br />
<div style="text-align: justify;">
Technically, its doesn't matter which tool you are selecting, the thing which differ is output only.There is not much change in development if you want to change the tool.So for this things what we are going to do is we will create one shell script which is going to fire this command and generate output.We will fetch that out put and will overide existing file in alfresco.</div>
<br />
Let's go further in development.<br />
<br />
The first step for developing this is to create shell script and executing it and testing it.<br />
<br />
<div style="text-align: justify;">
Create file called <i>transformation.sh </i>and before adding your command in it you have to add below line in it.If you are using windows you need to create batch file accordingly.</div>
<br />
<br />
<div class="p1">
<span class="s1"><b>unset LD_LIBRARY_PATH</b></span></div>
<div class="p1">
<span class="s1"><b><br /></b></span></div>
<div class="p1">
<div style="text-align: justify;">
<span class="s1">If you are not setting above in the script file you will face an error while conversation.</span>You can find that bug details on below link of alfresco.Its registered issue in alfresco.</div>
</div>
<div class="p1">
<span class="s1"><br /></span></div>
<div class="p1">
<span class="s1"><a href="https://issues.alfresco.com/jira/browse/ALF-19946">https://issues.alfresco.com/jira/browse/ALF-19946</a></span></div>
<i><br /></i>
<i><br /></i>
Once you create script in linux , you have to create action-executor in alfresco which fire script which we have created.You will be able to create action-executor by following below steps.<br />
<br />
<b>TransformerAction.java</b>
<br />
<pre class="brush: java" name="code">package com.ocr;
import java.io.File;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.repo.content.transform.ContentTransformerHelper;
import org.alfresco.repo.content.transform.ContentTransformerWorker;
import org.alfresco.service.cmr.repository.ContentIOException;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.MimetypeService;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.alfresco.util.TempFileProvider;
import org.alfresco.util.exec.RuntimeExec;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class TransformerAction extends ContentTransformerHelper implements ContentTransformerWorker {
private static final Log logger = LogFactory.getLog(TransformerAction.class);
private static final String VAR_SOURCE = "source";
private static final String VAR_TARGET = "target";
private RuntimeExec executer;
private RuntimeExec checkCommand;
//Injected
private MimetypeService mimetypeService;
private boolean available=true;
private Date lastChecked = new Date(0l);
private int checkFrequencyInSeconds=120;
public void setCheckFrequencyInSeconds(int frequency) {
checkFrequencyInSeconds=frequency;
}
public boolean isAvailable() {
Date refreshAvailabilityDate = new Date(lastChecked.getTime()+1000l*checkFrequencyInSeconds);
if (new Date().after(refreshAvailabilityDate)) {
test();
}
return available;
}
public void setMimetypeService(MimetypeService ms) {
mimetypeService=ms;
}
public void setTimeout(long timeout) {
pdfTimeout=timeout;
}
public long pdfTimeout=60000l;
public void setExecuter(RuntimeExec executer) {
this.executer = executer;
}
public void setCheckCommand(RuntimeExec checkCommand) {
this.checkCommand = checkCommand;
}
protected void test() {
try {
logger.debug("Testing availability");
RuntimeExec.ExecutionResult result = checkCommand.execute();
available=result.getSuccess();
logger.info("Is tesseract available? "+available);
}
catch (Exception e) {
available=false;
logger.warn("Check command ["+checkCommand.getCommand()+"] failed. Registering transform as unavailable for the next "+checkFrequencyInSeconds+" seconds");
}
}
public final void transform(ContentReader reader, ContentWriter writer, TransformationOptions options) throws Exception
{
try {
logger.debug("Beginning transform for "+reader.getContentData().getContentUrl());
String sourceMimetype = getMimetype(reader);
String targetMimetype = getMimetype(writer);
String sourceExtension = mimetypeService.getExtension(sourceMimetype);
String targetExtension = mimetypeService.getExtension(targetMimetype);
File sourceFile = TempFileProvider.createTempFile(getClass().getSimpleName() + "_source_", "." + sourceExtension);
File targetFile = TempFileProvider.createTempFile(getClass().getSimpleName() + "_target_","."+targetExtension);
logger.debug("Temp files created");
reader.getContent(sourceFile);
logger.debug("Source file written");
Map<string string=""> properties = new HashMap<string string="">(5);
properties.put(VAR_SOURCE, sourceFile.getAbsolutePath());
properties.put(VAR_TARGET, targetFile.getAbsolutePath());
RuntimeExec.ExecutionResult result = executer.execute(properties, pdfTimeout);
File actualLocation = new File(targetFile.getAbsolutePath());
actualLocation.renameTo(targetFile);
if (result.getExitValue() != 0 && result.getStdErr() != null && result.getStdErr().length() > 0) {
throw new ContentIOException("Failed to perform OCR transformation: \n" + result);
}
logger.debug("Transform executed");
writer.putContent(targetFile);
logger.info("Transform complete");
}
catch (Exception e) {
logger.error("Exception during transform", e);
throw e;
}
}
@Override
public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options) {
if (targetMimetype.equals("application/pdf")) {
if (sourceMimetype.equals("application/pdf")) {
return true;
}
}
return false;
}
@Override
public String getVersionString() {
return "Tesseract Transformer V1.0 - this method not implemented yet";
}
}
</string></string></pre>
<b>transformer-context.xml</b>
<br />
<pre class="brush: xml" name="code"><beans>
<bean class="org.alfresco.repo.content.transform.ProxyContentTransformer" id="transformer.pdf" parent="baseContentTransformer">
<property name="worker">
<ref bean="transformer.worker.ocr">
</ref></property>
<property name="explicitTransformations">
<list>
<bean class="org.alfresco.repo.content.transform.ExplictTransformationDetails">
<property name="sourceMimetype">
<value>image/png</value>
</property>
<property name="targetMimetype">
<value>text/plain</value>
</property>
</bean>
<bean class="org.alfresco.repo.content.transform.ExplictTransformationDetails">
<property name="sourceMimetype">
<value>image/jpeg</value>
</property>
<property name="targetMimetype">
<value>text/plain</value>
</property>
</bean>
<bean class="org.alfresco.repo.content.transform.ExplictTransformationDetails">
<property name="sourceMimetype">
<value>image/gif</value>
</property>
<property name="targetMimetype">
<value>text/plain</value>
</property>
</bean>
</list>
</property>
</bean>
<bean class="com.ocr.TransformerAction" id="transformer.worker.ocr">
<property name="mimetypeService">
<ref bean="mimetypeService">
</ref></property>
<property name="executer">
<bean class="org.alfresco.util.exec.RuntimeExec" name="transformer.pdf.Command">
<property name="commandsAndArguments">
<map>
<entry key=".*">
<list>
<value>/usr/bin/scriptname.sh</value><!-- Reference to your script file which we created in first phase -->
<value>${source}</value>
<value>${target}</value>
</list>
</entry>
</map>
</property>
</bean>
</property>
<property name="checkCommand">
<bean class="org.alfresco.util.exec.RuntimeExec" name="transformer.pdf.CheckCommand">
<property name="commandsAndArguments">
<map>
<entry key=".*">
<list>
<value>/usr/bin/scriptname.sh</value><!-- Reference to your script file which we created in first phase -->
<value>-v</value>
</list>
</entry>
</map>
</property>
</bean>
</property>
</bean>
</beans>
</pre>
<b>OCR.properties</b>
<br />
<pre class="brush: java" name="code">transformer.pdf.title=PDF OCR
transformer.pdf.description=Content file will be converted to PDF and OCR process will produce a searchable PDF file.
transformer.pdf.continue-on-error.display-label=Continue on error
</pre>
<div style="text-align: justify;">
Once you create this files in your project, you will be able to see action under rule called <b> PDF OCR</b>.Select it as a rule and do other configuration as per your requirement.You will be able to perform PDF to PDF conversation.
Hope this helps.
</div>
</div>
<div class="blogger-post-footer">https://scontent-b-mxp.xx.fbcdn.net/hphotos-xap1/v/t1.0-9/10675541_896261013719814_5601513019470361090_n.jpg?oh=741b05a81becaae8bce36db141948a4a&oe=5531762A</div>Krutik Jayswalhttp://www.blogger.com/profile/16691396948811505379noreply@blogger.comtag:blogger.com,1999:blog-2571457445842624811.post-69738188096444086242016-07-18T04:08:00.003-07:002017-06-22T00:48:23.818-07:00Share Dashlet Using YUI<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<h3 style="text-align: left;">
</h3>
<div>
<div style="text-align: justify;">
Dashlet is part of alfresco share dashboard.Alfresco provides some out of box dashlets like "My Task", "RSS Feed", "Web View","My Calendar", "My Sites" and many other dashlets are available.You can test all this dashlet by adding it in your dashboard.User can add dashlets on two places. One of them is <i>User Dashboard </i>and other is <i>Site Dashboard.</i></div>
<div style="text-align: justify;">
<i><br /></i></div>
<div style="text-align: justify;">
<i>Technically , </i>Dashlet is nothing but webscript.Webscript which created in alfresco share.</div>
</div>
<div>
<div style="text-align: justify;">
Developer can create both kind of dashlet which can be added on both places User Dashboar as well as SiteDashboard.</div>
<div style="text-align: justify;">
<br /></div>
</div>
<div>
<div style="text-align: justify;">
<br /></div>
</div>
<div>
<div style="text-align: justify;">
For creating dashlet you will need to have basic knowledge of webscript. If you dont have any knowledge regarding same you can follow below link for deep knowledge.</div>
</div>
<div>
<div style="text-align: justify;">
<a href="https://wiki.alfresco.com/wiki/Web_Scripts">https://wiki.alfresco.com/wiki/Web_Scripts</a></div>
</div>
<div>
<div style="text-align: justify;">
<br /></div>
</div>
<div>
<div style="text-align: justify;">
For creating dashlet in alfresco share you will need to create below files, Its not required to create all files.It depends on you requirement, and how you want to make behave your share dashlet. The importance of all files is explained as below.</div>
<div style="text-align: justify;">
<br /></div>
<!--[if gte mso 9]><xml>
<o:OfficeDocumentSettings>
<o:AllowPNG/>
<o:PixelsPerInch>96</o:PixelsPerInch>
</o:OfficeDocumentSettings>
</xml><![endif]-->
<!--[if gte mso 9]><xml>
<w:WordDocument>
<w:View>Normal</w:View>
<w:Zoom>0</w:Zoom>
<w:TrackMoves/>
<w:TrackFormatting/>
<w:PunctuationKerning/>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:DoNotPromoteQF/>
<w:LidThemeOther>EN-US</w:LidThemeOther>
<w:LidThemeAsian>JA</w:LidThemeAsian>
<w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript>
<w:Compatibility>
<w:BreakWrappedTables/>
<w:SnapToGridInCell/>
<w:WrapTextWithPunct/>
<w:UseAsianBreakRules/>
<w:DontGrowAutofit/>
<w:SplitPgBreakAndParaMark/>
<w:EnableOpenTypeKerning/>
<w:DontFlipMirrorIndents/>
<w:OverrideTableStyleHps/>
<w:UseFELayout/>
</w:Compatibility>
<m:mathPr>
<m:mathFont m:val="Cambria Math"/>
<m:brkBin m:val="before"/>
<m:brkBinSub m:val="--"/>
<m:smallFrac m:val="off"/>
<m:dispDef/>
<m:lMargin m:val="0"/>
<m:rMargin m:val="0"/>
<m:defJc m:val="centerGroup"/>
<m:wrapIndent m:val="1440"/>
<m:intLim m:val="subSup"/>
<m:naryLim m:val="undOvr"/>
</m:mathPr></w:WordDocument>
</xml><![endif]--><!--[if gte mso 9]><xml>
<w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="false"
DefSemiHidden="false" DefQFormat="false" DefPriority="99"
LatentStyleCount="380">
<w:LsdException Locked="false" Priority="0" QFormat="true" Name="Normal"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 1"/>
<w:LsdException Locked="false" Priority="9" SemiHidden="true"
UnhideWhenUsed="true" QFormat="true" Name="heading 2"/>
<w:LsdException Locked="false" Priority="9" SemiHidden="true"
UnhideWhenUsed="true" QFormat="true" Name="heading 3"/>
<w:LsdException Locked="false" Priority="9" SemiHidden="true"
UnhideWhenUsed="true" QFormat="true" Name="heading 4"/>
<w:LsdException Locked="false" Priority="9" SemiHidden="true"
UnhideWhenUsed="true" QFormat="true" Name="heading 5"/>
<w:LsdException Locked="false" Priority="9" SemiHidden="true"
UnhideWhenUsed="true" QFormat="true" Name="heading 6"/>
<w:LsdException Locked="false" Priority="9" SemiHidden="true"
UnhideWhenUsed="true" QFormat="true" Name="heading 7"/>
<w:LsdException Locked="false" Priority="9" SemiHidden="true"
UnhideWhenUsed="true" QFormat="true" Name="heading 8"/>
<w:LsdException Locked="false" Priority="9" SemiHidden="true"
UnhideWhenUsed="true" QFormat="true" Name="heading 9"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="index 1"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="index 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="index 3"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="index 4"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="index 5"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="index 6"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="index 7"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="index 8"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="index 9"/>
<w:LsdException Locked="false" Priority="39" SemiHidden="true"
UnhideWhenUsed="true" Name="toc 1"/>
<w:LsdException Locked="false" Priority="39" SemiHidden="true"
UnhideWhenUsed="true" Name="toc 2"/>
<w:LsdException Locked="false" Priority="39" SemiHidden="true"
UnhideWhenUsed="true" Name="toc 3"/>
<w:LsdException Locked="false" Priority="39" SemiHidden="true"
UnhideWhenUsed="true" Name="toc 4"/>
<w:LsdException Locked="false" Priority="39" SemiHidden="true"
UnhideWhenUsed="true" Name="toc 5"/>
<w:LsdException Locked="false" Priority="39" SemiHidden="true"
UnhideWhenUsed="true" Name="toc 6"/>
<w:LsdException Locked="false" Priority="39" SemiHidden="true"
UnhideWhenUsed="true" Name="toc 7"/>
<w:LsdException Locked="false" Priority="39" SemiHidden="true"
UnhideWhenUsed="true" Name="toc 8"/>
<w:LsdException Locked="false" Priority="39" SemiHidden="true"
UnhideWhenUsed="true" Name="toc 9"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Normal Indent"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="footnote text"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="annotation text"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="header"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="footer"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="index heading"/>
<w:LsdException Locked="false" Priority="35" SemiHidden="true"
UnhideWhenUsed="true" QFormat="true" Name="caption"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="table of figures"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="envelope address"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="envelope return"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="footnote reference"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="annotation reference"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="line number"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="page number"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="endnote reference"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="endnote text"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="table of authorities"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="macro"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="toa heading"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="List"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="List Bullet"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="List Number"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="List 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="List 3"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="List 4"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="List 5"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="List Bullet 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="List Bullet 3"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="List Bullet 4"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="List Bullet 5"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="List Number 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="List Number 3"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="List Number 4"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="List Number 5"/>
<w:LsdException Locked="false" Priority="10" QFormat="true" Name="Title"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Closing"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Signature"/>
<w:LsdException Locked="false" Priority="1" SemiHidden="true"
UnhideWhenUsed="true" Name="Default Paragraph Font"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Body Text"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Body Text Indent"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="List Continue"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="List Continue 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="List Continue 3"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="List Continue 4"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="List Continue 5"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Message Header"/>
<w:LsdException Locked="false" Priority="11" QFormat="true" Name="Subtitle"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Salutation"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Date"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Body Text First Indent"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Body Text First Indent 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Note Heading"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Body Text 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Body Text 3"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Body Text Indent 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Body Text Indent 3"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Block Text"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Hyperlink"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="FollowedHyperlink"/>
<w:LsdException Locked="false" Priority="22" QFormat="true" Name="Strong"/>
<w:LsdException Locked="false" Priority="20" QFormat="true" Name="Emphasis"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Document Map"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Plain Text"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="E-mail Signature"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="HTML Top of Form"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="HTML Bottom of Form"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Normal (Web)"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="HTML Acronym"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="HTML Address"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="HTML Cite"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="HTML Code"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="HTML Definition"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="HTML Keyboard"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="HTML Preformatted"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="HTML Sample"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="HTML Typewriter"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="HTML Variable"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Normal Table"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="annotation subject"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="No List"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Outline List 1"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Outline List 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Outline List 3"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table Simple 1"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table Simple 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table Simple 3"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table Classic 1"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table Classic 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table Classic 3"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table Classic 4"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table Colorful 1"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table Colorful 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table Colorful 3"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table Columns 1"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table Columns 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table Columns 3"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table Columns 4"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table Columns 5"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table Grid 1"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table Grid 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table Grid 3"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table Grid 4"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table Grid 5"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table Grid 6"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table Grid 7"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table Grid 8"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table List 1"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table List 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table List 3"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table List 4"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table List 5"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table List 6"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table List 7"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table List 8"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table 3D effects 1"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table 3D effects 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table 3D effects 3"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table Contemporary"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table Elegant"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table Professional"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table Subtle 1"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table Subtle 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table Web 1"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table Web 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table Web 3"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Balloon Text"/>
<w:LsdException Locked="false" Priority="39" Name="Table Grid"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Table Theme"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Note Level 1"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Note Level 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Note Level 3"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Note Level 4"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Note Level 5"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Note Level 6"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Note Level 7"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Note Level 8"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
Name="Note Level 9"/>
<w:LsdException Locked="false" SemiHidden="true" Name="Placeholder Text"/>
<w:LsdException Locked="false" Priority="1" QFormat="true" Name="No Spacing"/>
<w:LsdException Locked="false" Priority="60" Name="Light Shading"/>
<w:LsdException Locked="false" Priority="61" Name="Light List"/>
<w:LsdException Locked="false" Priority="62" Name="Light Grid"/>
<w:LsdException Locked="false" Priority="63" Name="Medium Shading 1"/>
<w:LsdException Locked="false" Priority="64" Name="Medium Shading 2"/>
<w:LsdException Locked="false" Priority="65" Name="Medium List 1"/>
<w:LsdException Locked="false" Priority="66" Name="Medium List 2"/>
<w:LsdException Locked="false" Priority="67" Name="Medium Grid 1"/>
<w:LsdException Locked="false" Priority="68" Name="Medium Grid 2"/>
<w:LsdException Locked="false" Priority="69" Name="Medium Grid 3"/>
<w:LsdException Locked="false" Priority="70" Name="Dark List"/>
<w:LsdException Locked="false" Priority="71" Name="Colorful Shading"/>
<w:LsdException Locked="false" Priority="72" Name="Colorful List"/>
<w:LsdException Locked="false" Priority="73" Name="Colorful Grid"/>
<w:LsdException Locked="false" Priority="60" Name="Light Shading Accent 1"/>
<w:LsdException Locked="false" Priority="61" Name="Light List Accent 1"/>
<w:LsdException Locked="false" Priority="62" Name="Light Grid Accent 1"/>
<w:LsdException Locked="false" Priority="63" Name="Medium Shading 1 Accent 1"/>
<w:LsdException Locked="false" Priority="64" Name="Medium Shading 2 Accent 1"/>
<w:LsdException Locked="false" Priority="65" Name="Medium List 1 Accent 1"/>
<w:LsdException Locked="false" SemiHidden="true" Name="Revision"/>
<w:LsdException Locked="false" Priority="34" QFormat="true"
Name="List Paragraph"/>
<w:LsdException Locked="false" Priority="29" QFormat="true" Name="Quote"/>
<w:LsdException Locked="false" Priority="30" QFormat="true"
Name="Intense Quote"/>
<w:LsdException Locked="false" Priority="66" Name="Medium List 2 Accent 1"/>
<w:LsdException Locked="false" Priority="67" Name="Medium Grid 1 Accent 1"/>
<w:LsdException Locked="false" Priority="68" Name="Medium Grid 2 Accent 1"/>
<w:LsdException Locked="false" Priority="69" Name="Medium Grid 3 Accent 1"/>
<w:LsdException Locked="false" Priority="70" Name="Dark List Accent 1"/>
<w:LsdException Locked="false" Priority="71" Name="Colorful Shading Accent 1"/>
<w:LsdException Locked="false" Priority="72" Name="Colorful List Accent 1"/>
<w:LsdException Locked="false" Priority="73" Name="Colorful Grid Accent 1"/>
<w:LsdException Locked="false" Priority="60" Name="Light Shading Accent 2"/>
<w:LsdException Locked="false" Priority="61" Name="Light List Accent 2"/>
<w:LsdException Locked="false" Priority="62" Name="Light Grid Accent 2"/>
<w:LsdException Locked="false" Priority="63" Name="Medium Shading 1 Accent 2"/>
<w:LsdException Locked="false" Priority="64" Name="Medium Shading 2 Accent 2"/>
<w:LsdException Locked="false" Priority="65" Name="Medium List 1 Accent 2"/>
<w:LsdException Locked="false" Priority="66" Name="Medium List 2 Accent 2"/>
<w:LsdException Locked="false" Priority="67" Name="Medium Grid 1 Accent 2"/>
<w:LsdException Locked="false" Priority="68" Name="Medium Grid 2 Accent 2"/>
<w:LsdException Locked="false" Priority="69" Name="Medium Grid 3 Accent 2"/>
<w:LsdException Locked="false" Priority="70" Name="Dark List Accent 2"/>
<w:LsdException Locked="false" Priority="71" Name="Colorful Shading Accent 2"/>
<w:LsdException Locked="false" Priority="72" Name="Colorful List Accent 2"/>
<w:LsdException Locked="false" Priority="73" Name="Colorful Grid Accent 2"/>
<w:LsdException Locked="false" Priority="60" Name="Light Shading Accent 3"/>
<w:LsdException Locked="false" Priority="61" Name="Light List Accent 3"/>
<w:LsdException Locked="false" Priority="62" Name="Light Grid Accent 3"/>
<w:LsdException Locked="false" Priority="63" Name="Medium Shading 1 Accent 3"/>
<w:LsdException Locked="false" Priority="64" Name="Medium Shading 2 Accent 3"/>
<w:LsdException Locked="false" Priority="65" Name="Medium List 1 Accent 3"/>
<w:LsdException Locked="false" Priority="66" Name="Medium List 2 Accent 3"/>
<w:LsdException Locked="false" Priority="67" Name="Medium Grid 1 Accent 3"/>
<w:LsdException Locked="false" Priority="68" Name="Medium Grid 2 Accent 3"/>
<w:LsdException Locked="false" Priority="69" Name="Medium Grid 3 Accent 3"/>
<w:LsdException Locked="false" Priority="70" Name="Dark List Accent 3"/>
<w:LsdException Locked="false" Priority="71" Name="Colorful Shading Accent 3"/>
<w:LsdException Locked="false" Priority="72" Name="Colorful List Accent 3"/>
<w:LsdException Locked="false" Priority="73" Name="Colorful Grid Accent 3"/>
<w:LsdException Locked="false" Priority="60" Name="Light Shading Accent 4"/>
<w:LsdException Locked="false" Priority="61" Name="Light List Accent 4"/>
<w:LsdException Locked="false" Priority="62" Name="Light Grid Accent 4"/>
<w:LsdException Locked="false" Priority="63" Name="Medium Shading 1 Accent 4"/>
<w:LsdException Locked="false" Priority="64" Name="Medium Shading 2 Accent 4"/>
<w:LsdException Locked="false" Priority="65" Name="Medium List 1 Accent 4"/>
<w:LsdException Locked="false" Priority="66" Name="Medium List 2 Accent 4"/>
<w:LsdException Locked="false" Priority="67" Name="Medium Grid 1 Accent 4"/>
<w:LsdException Locked="false" Priority="68" Name="Medium Grid 2 Accent 4"/>
<w:LsdException Locked="false" Priority="69" Name="Medium Grid 3 Accent 4"/>
<w:LsdException Locked="false" Priority="70" Name="Dark List Accent 4"/>
<w:LsdException Locked="false" Priority="71" Name="Colorful Shading Accent 4"/>
<w:LsdException Locked="false" Priority="72" Name="Colorful List Accent 4"/>
<w:LsdException Locked="false" Priority="73" Name="Colorful Grid Accent 4"/>
<w:LsdException Locked="false" Priority="60" Name="Light Shading Accent 5"/>
<w:LsdException Locked="false" Priority="61" Name="Light List Accent 5"/>
<w:LsdException Locked="false" Priority="62" Name="Light Grid Accent 5"/>
<w:LsdException Locked="false" Priority="63" Name="Medium Shading 1 Accent 5"/>
<w:LsdException Locked="false" Priority="64" Name="Medium Shading 2 Accent 5"/>
<w:LsdException Locked="false" Priority="65" Name="Medium List 1 Accent 5"/>
<w:LsdException Locked="false" Priority="66" Name="Medium List 2 Accent 5"/>
<w:LsdException Locked="false" Priority="67" Name="Medium Grid 1 Accent 5"/>
<w:LsdException Locked="false" Priority="68" Name="Medium Grid 2 Accent 5"/>
<w:LsdException Locked="false" Priority="69" Name="Medium Grid 3 Accent 5"/>
<w:LsdException Locked="false" Priority="70" Name="Dark List Accent 5"/>
<w:LsdException Locked="false" Priority="71" Name="Colorful Shading Accent 5"/>
<w:LsdException Locked="false" Priority="72" Name="Colorful List Accent 5"/>
<w:LsdException Locked="false" Priority="73" Name="Colorful Grid Accent 5"/>
<w:LsdException Locked="false" Priority="60" Name="Light Shading Accent 6"/>
<w:LsdException Locked="false" Priority="61" Name="Light List Accent 6"/>
<w:LsdException Locked="false" Priority="62" Name="Light Grid Accent 6"/>
<w:LsdException Locked="false" Priority="63" Name="Medium Shading 1 Accent 6"/>
<w:LsdException Locked="false" Priority="64" Name="Medium Shading 2 Accent 6"/>
<w:LsdException Locked="false" Priority="65" Name="Medium List 1 Accent 6"/>
<w:LsdException Locked="false" Priority="66" Name="Medium List 2 Accent 6"/>
<w:LsdException Locked="false" Priority="67" Name="Medium Grid 1 Accent 6"/>
<w:LsdException Locked="false" Priority="68" Name="Medium Grid 2 Accent 6"/>
<w:LsdException Locked="false" Priority="69" Name="Medium Grid 3 Accent 6"/>
<w:LsdException Locked="false" Priority="70" Name="Dark List Accent 6"/>
<w:LsdException Locked="false" Priority="71" Name="Colorful Shading Accent 6"/>
<w:LsdException Locked="false" Priority="72" Name="Colorful List Accent 6"/>
<w:LsdException Locked="false" Priority="73" Name="Colorful Grid Accent 6"/>
<w:LsdException Locked="false" Priority="19" QFormat="true"
Name="Subtle Emphasis"/>
<w:LsdException Locked="false" Priority="21" QFormat="true"
Name="Intense Emphasis"/>
<w:LsdException Locked="false" Priority="31" QFormat="true"
Name="Subtle Reference"/>
<w:LsdException Locked="false" Priority="32" QFormat="true"
Name="Intense Reference"/>
<w:LsdException Locked="false" Priority="33" QFormat="true" Name="Book Title"/>
<w:LsdException Locked="false" Priority="37" SemiHidden="true"
UnhideWhenUsed="true" Name="Bibliography"/>
<w:LsdException Locked="false" Priority="39" SemiHidden="true"
UnhideWhenUsed="true" QFormat="true" Name="TOC Heading"/>
<w:LsdException Locked="false" Priority="41" Name="Plain Table 1"/>
<w:LsdException Locked="false" Priority="42" Name="Plain Table 2"/>
<w:LsdException Locked="false" Priority="43" Name="Plain Table 3"/>
<w:LsdException Locked="false" Priority="44" Name="Plain Table 4"/>
<w:LsdException Locked="false" Priority="45" Name="Plain Table 5"/>
<w:LsdException Locked="false" Priority="40" Name="Grid Table Light"/>
<w:LsdException Locked="false" Priority="46" Name="Grid Table 1 Light"/>
<w:LsdException Locked="false" Priority="47" Name="Grid Table 2"/>
<w:LsdException Locked="false" Priority="48" Name="Grid Table 3"/>
<w:LsdException Locked="false" Priority="49" Name="Grid Table 4"/>
<w:LsdException Locked="false" Priority="50" Name="Grid Table 5 Dark"/>
<w:LsdException Locked="false" Priority="51" Name="Grid Table 6 Colorful"/>
<w:LsdException Locked="false" Priority="52" Name="Grid Table 7 Colorful"/>
<w:LsdException Locked="false" Priority="46"
Name="Grid Table 1 Light Accent 1"/>
<w:LsdException Locked="false" Priority="47" Name="Grid Table 2 Accent 1"/>
<w:LsdException Locked="false" Priority="48" Name="Grid Table 3 Accent 1"/>
<w:LsdException Locked="false" Priority="49" Name="Grid Table 4 Accent 1"/>
<w:LsdException Locked="false" Priority="50" Name="Grid Table 5 Dark Accent 1"/>
<w:LsdException Locked="false" Priority="51"
Name="Grid Table 6 Colorful Accent 1"/>
<w:LsdException Locked="false" Priority="52"
Name="Grid Table 7 Colorful Accent 1"/>
<w:LsdException Locked="false" Priority="46"
Name="Grid Table 1 Light Accent 2"/>
<w:LsdException Locked="false" Priority="47" Name="Grid Table 2 Accent 2"/>
<w:LsdException Locked="false" Priority="48" Name="Grid Table 3 Accent 2"/>
<w:LsdException Locked="false" Priority="49" Name="Grid Table 4 Accent 2"/>
<w:LsdException Locked="false" Priority="50" Name="Grid Table 5 Dark Accent 2"/>
<w:LsdException Locked="false" Priority="51"
Name="Grid Table 6 Colorful Accent 2"/>
<w:LsdException Locked="false" Priority="52"
Name="Grid Table 7 Colorful Accent 2"/>
<w:LsdException Locked="false" Priority="46"
Name="Grid Table 1 Light Accent 3"/>
<w:LsdException Locked="false" Priority="47" Name="Grid Table 2 Accent 3"/>
<w:LsdException Locked="false" Priority="48" Name="Grid Table 3 Accent 3"/>
<w:LsdException Locked="false" Priority="49" Name="Grid Table 4 Accent 3"/>
<w:LsdException Locked="false" Priority="50" Name="Grid Table 5 Dark Accent 3"/>
<w:LsdException Locked="false" Priority="51"
Name="Grid Table 6 Colorful Accent 3"/>
<w:LsdException Locked="false" Priority="52"
Name="Grid Table 7 Colorful Accent 3"/>
<w:LsdException Locked="false" Priority="46"
Name="Grid Table 1 Light Accent 4"/>
<w:LsdException Locked="false" Priority="47" Name="Grid Table 2 Accent 4"/>
<w:LsdException Locked="false" Priority="48" Name="Grid Table 3 Accent 4"/>
<w:LsdException Locked="false" Priority="49" Name="Grid Table 4 Accent 4"/>
<w:LsdException Locked="false" Priority="50" Name="Grid Table 5 Dark Accent 4"/>
<w:LsdException Locked="false" Priority="51"
Name="Grid Table 6 Colorful Accent 4"/>
<w:LsdException Locked="false" Priority="52"
Name="Grid Table 7 Colorful Accent 4"/>
<w:LsdException Locked="false" Priority="46"
Name="Grid Table 1 Light Accent 5"/>
<w:LsdException Locked="false" Priority="47" Name="Grid Table 2 Accent 5"/>
<w:LsdException Locked="false" Priority="48" Name="Grid Table 3 Accent 5"/>
<w:LsdException Locked="false" Priority="49" Name="Grid Table 4 Accent 5"/>
<w:LsdException Locked="false" Priority="50" Name="Grid Table 5 Dark Accent 5"/>
<w:LsdException Locked="false" Priority="51"
Name="Grid Table 6 Colorful Accent 5"/>
<w:LsdException Locked="false" Priority="52"
Name="Grid Table 7 Colorful Accent 5"/>
<w:LsdException Locked="false" Priority="46"
Name="Grid Table 1 Light Accent 6"/>
<w:LsdException Locked="false" Priority="47" Name="Grid Table 2 Accent 6"/>
<w:LsdException Locked="false" Priority="48" Name="Grid Table 3 Accent 6"/>
<w:LsdException Locked="false" Priority="49" Name="Grid Table 4 Accent 6"/>
<w:LsdException Locked="false" Priority="50" Name="Grid Table 5 Dark Accent 6"/>
<w:LsdException Locked="false" Priority="51"
Name="Grid Table 6 Colorful Accent 6"/>
<w:LsdException Locked="false" Priority="52"
Name="Grid Table 7 Colorful Accent 6"/>
<w:LsdException Locked="false" Priority="46" Name="List Table 1 Light"/>
<w:LsdException Locked="false" Priority="47" Name="List Table 2"/>
<w:LsdException Locked="false" Priority="48" Name="List Table 3"/>
<w:LsdException Locked="false" Priority="49" Name="List Table 4"/>
<w:LsdException Locked="false" Priority="50" Name="List Table 5 Dark"/>
<w:LsdException Locked="false" Priority="51" Name="List Table 6 Colorful"/>
<w:LsdException Locked="false" Priority="52" Name="List Table 7 Colorful"/>
<w:LsdException Locked="false" Priority="46"
Name="List Table 1 Light Accent 1"/>
<w:LsdException Locked="false" Priority="47" Name="List Table 2 Accent 1"/>
<w:LsdException Locked="false" Priority="48" Name="List Table 3 Accent 1"/>
<w:LsdException Locked="false" Priority="49" Name="List Table 4 Accent 1"/>
<w:LsdException Locked="false" Priority="50" Name="List Table 5 Dark Accent 1"/>
<w:LsdException Locked="false" Priority="51"
Name="List Table 6 Colorful Accent 1"/>
<w:LsdException Locked="false" Priority="52"
Name="List Table 7 Colorful Accent 1"/>
<w:LsdException Locked="false" Priority="46"
Name="List Table 1 Light Accent 2"/>
<w:LsdException Locked="false" Priority="47" Name="List Table 2 Accent 2"/>
<w:LsdException Locked="false" Priority="48" Name="List Table 3 Accent 2"/>
<w:LsdException Locked="false" Priority="49" Name="List Table 4 Accent 2"/>
<w:LsdException Locked="false" Priority="50" Name="List Table 5 Dark Accent 2"/>
<w:LsdException Locked="false" Priority="51"
Name="List Table 6 Colorful Accent 2"/>
<w:LsdException Locked="false" Priority="52"
Name="List Table 7 Colorful Accent 2"/>
<w:LsdException Locked="false" Priority="46"
Name="List Table 1 Light Accent 3"/>
<w:LsdException Locked="false" Priority="47" Name="List Table 2 Accent 3"/>
<w:LsdException Locked="false" Priority="48" Name="List Table 3 Accent 3"/>
<w:LsdException Locked="false" Priority="49" Name="List Table 4 Accent 3"/>
<w:LsdException Locked="false" Priority="50" Name="List Table 5 Dark Accent 3"/>
<w:LsdException Locked="false" Priority="51"
Name="List Table 6 Colorful Accent 3"/>
<w:LsdException Locked="false" Priority="52"
Name="List Table 7 Colorful Accent 3"/>
<w:LsdException Locked="false" Priority="46"
Name="List Table 1 Light Accent 4"/>
<w:LsdException Locked="false" Priority="47" Name="List Table 2 Accent 4"/>
<w:LsdException Locked="false" Priority="48" Name="List Table 3 Accent 4"/>
<w:LsdException Locked="false" Priority="49" Name="List Table 4 Accent 4"/>
<w:LsdException Locked="false" Priority="50" Name="List Table 5 Dark Accent 4"/>
<w:LsdException Locked="false" Priority="51"
Name="List Table 6 Colorful Accent 4"/>
<w:LsdException Locked="false" Priority="52"
Name="List Table 7 Colorful Accent 4"/>
<w:LsdException Locked="false" Priority="46"
Name="List Table 1 Light Accent 5"/>
<w:LsdException Locked="false" Priority="47" Name="List Table 2 Accent 5"/>
<w:LsdException Locked="false" Priority="48" Name="List Table 3 Accent 5"/>
<w:LsdException Locked="false" Priority="49" Name="List Table 4 Accent 5"/>
<w:LsdException Locked="false" Priority="50" Name="List Table 5 Dark Accent 5"/>
<w:LsdException Locked="false" Priority="51"
Name="List Table 6 Colorful Accent 5"/>
<w:LsdException Locked="false" Priority="52"
Name="List Table 7 Colorful Accent 5"/>
<w:LsdException Locked="false" Priority="46"
Name="List Table 1 Light Accent 6"/>
<w:LsdException Locked="false" Priority="47" Name="List Table 2 Accent 6"/>
<w:LsdException Locked="false" Priority="48" Name="List Table 3 Accent 6"/>
<w:LsdException Locked="false" Priority="49" Name="List Table 4 Accent 6"/>
<w:LsdException Locked="false" Priority="50" Name="List Table 5 Dark Accent 6"/>
<w:LsdException Locked="false" Priority="51"
Name="List Table 6 Colorful Accent 6"/>
<w:LsdException Locked="false" Priority="52"
Name="List Table 7 Colorful Accent 6"/>
</w:LatentStyles>
</xml><![endif]-->
<!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Table Normal";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-parent:"";
mso-padding-alt:0in 5.4pt 0in 5.4pt;
mso-para-margin:0in;
mso-para-margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:12.0pt;
font-family:Calibri;
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;}
table.MsoTableGrid
{mso-style-name:"Table Grid";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-priority:39;
mso-style-unhide:no;
border:solid windowtext 1.0pt;
mso-border-alt:solid windowtext .5pt;
mso-padding-alt:0in 5.4pt 0in 5.4pt;
mso-border-insideh:.5pt solid windowtext;
mso-border-insidev:.5pt solid windowtext;
mso-para-margin:0in;
mso-para-margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:12.0pt;
font-family:Calibri;
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;}
</style>
<![endif]-->
<!--StartFragment-->
<!--EndFragment--><br />
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; text-align: justify;">
<tbody>
<tr style="mso-yfti-firstrow: yes; mso-yfti-irow: 0;">
<td style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 155.8pt;" valign="top" width="156"><div class="MsoNormal">
FileType</div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 155.85pt;" valign="top" width="156"><div class="MsoNormal">
Description</div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 155.85pt;" valign="top" width="156"><div class="MsoNormal">
Suffix</div>
</td>
</tr>
<tr style="mso-yfti-irow: 1;">
<td style="border-top: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 155.8pt;" valign="top" width="156"><div class="MsoNormal">
Descriptor </div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 155.85pt;" valign="top" width="156"><div class="MsoNormal">
Dashlet descriptor contains the definition of dashlet.For
example ,family of dashlet,URL of dashlet etc…</div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 155.85pt;" valign="top" width="156"><div class="MsoNormal">
*get.desc.xml</div>
</td>
</tr>
<tr style="mso-yfti-irow: 2;">
<td style="border-top: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 155.8pt;" valign="top" width="156"><div class="MsoNormal">
Javascript Controller</div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 155.85pt;" valign="top" width="156"><div class="MsoNormal">
Controller of dashlet from where information are passed to
template engine(freemarker)</div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 155.85pt;" valign="top" width="156"><div class="MsoNormal">
*.js</div>
</td>
</tr>
<tr style="mso-yfti-irow: 3;">
<td style="border-top: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 155.8pt;" valign="top" width="156"><div class="MsoNormal">
Template Type</div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 155.85pt;" valign="top" width="156"><div class="MsoNormal">
It renderes the output.</div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 155.85pt;" valign="top" width="156"><div class="MsoNormal">
.html.ftl</div>
</td>
</tr>
<tr style="mso-yfti-irow: 4;">
<td style="border-top: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 155.8pt;" valign="top" width="156"><div class="MsoNormal">
Header</div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 155.85pt;" valign="top" width="156"><div class="MsoNormal">
Includes style sheet and client side javascript.<b>(deprecated)</b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 155.85pt;" valign="top" width="156"><div class="MsoNormal">
*.head.ftl</div>
</td>
</tr>
<tr style="mso-yfti-irow: 5; mso-yfti-lastrow: yes;">
<td style="border-top: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 155.8pt;" valign="top" width="156"><div class="MsoNormal">
YUI Script</div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 155.85pt;" valign="top" width="156"><div class="MsoNormal">
Client side javascript module.</div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 155.85pt;" valign="top" width="156"><div class="MsoNormal">
SampleDashlet.js</div>
</td>
</tr>
</tbody></table>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Above are the files which are used for creating dashlet. Below is an simple dashlet.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b>sample.get.desc.xml</b></div>
<div style="text-align: justify;">
<b>sample.get.js</b></div>
<div style="text-align: justify;">
<b>sample.get.html.ftl</b></div>
<div style="text-align: justify;">
<b>sample.get.head.ftl(deprecated)</b></div>
<div style="text-align: justify;">
<b>sample.js</b></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Here please not the <b>difference</b> between <b>sample.js and sample.get.js. </b><i>sample.js</i> is client side javascript file while sample.get.js is server side javascript file. Many people get confused in this.This is the first thing which you should remember while developing a dashlet.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Below is an example for simple dashlet in alfresco.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
sample.get.desc.xml
</div>
<pre class="brush: xml" name="code"><div style="text-align: justify;">
</div>
<webscript><div style="text-align: justify;">
<shortname>Sample Dashlet</shortname></div>
<div style="text-align: justify;">
<description>Provide Search of people and display in a list</description></div>
<div style="text-align: justify;">
<family>user-dashlet</family></div>
<div style="text-align: justify;">
<url>/components/dashlets/member-directory</url></div>
</webscript><div style="text-align: justify;">
</div>
</pre>
<div style="text-align: justify;">
sample.get.js
</div>
<pre class="brush: javascript" name="code" style="text-align: justify;">model.name="Krutik";
</pre>
<div style="text-align: justify;">
SampleDashlet.js
</div>
<pre class="brush: javascript" name="code" style="text-align: justify;">model.name="Krutik";
</pre>
<div style="text-align: justify;">
sample.get.html.ftl
</div>
<pre class="brush: html" name="code"><div style="text-align: justify;">
<#assign id = args.htmlid?html></div>
<@markup id="js">
<div style="text-align: justify;">
<@script type="text/javascript" src="${url.context}/res/components/sample-dashlet/SampleDashlet.js" group="dashlets"/></div>
</@>
<@markup id="widgets">
<@createWidgets group="dashlets"/>
</@>
<@markup id="html">
<div style="text-align: justify;">
</div>
<div class="dashlet">
<div class="title">
<div style="text-align: justify;">
Sample Dashlet</div>
</div>
<div class="body" id="${id}-memberdir">
<div style="padding: 10px;">
<div style="text-align: justify;">
<a href="https://www.blogger.com/blogger.g?blogID=2571457445842624811#" id="${id}-link">Click me</a></div>
<br />
<div style="text-align: justify;">
The user dashboard displays when users arrive to a dashboard of user, and contains dashlets. A dashlet offers a quick view into the content or activities of the user. You can use the out-of-the-box dashlets or add your own custom dashlets in to your dashboard.</div>
<div style="text-align: justify;">
</div>
<br />
<br />
<div style="text-align: justify;">
By ${name}</div>
<div style="text-align: justify;">
</div>
</div>
</div>
</div>
<div style="text-align: justify;">
</div>
<div style="text-align: justify;">
</@> </div>
<script type="text/javascript">
new Alfresco.dashlet.SampleDashlet("${id}");
</script><span style="font-family: "times";"><span style="white-space: normal;">
</span></span></pre>
<div class="separator" style="clear: both; text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b>SampleDashlet.js</b>
</div>
<pre class="brush: javascript" name="code"><div style="text-align: justify;">
(function()</div>
{
/**
<div style="text-align: justify;">
* YUI Library aliases</div>
*/
<div style="text-align: justify;">
Event = YAHOO.util.Event;</div>
var Dom = YAHOO.util.Dom,
<div style="text-align: justify;">
* Alfresco Slingshot aliases</div>
/**
*/
<div style="text-align: justify;">
var $html = Alfresco.util.encodeHTML,</div>
$combine = Alfresco.util.combinePaths;
<div style="text-align: justify;">
Alfresco.dashlet.SampleDashlet = function SampleDashlet_constructor(htmlId)</div>
{
<div style="text-align: justify;">
};</div>
return Alfresco.dashlet.SampleDashlet.superclass.constructor.call(this, "Alfresco.dashlet.SampleDashlet", htmlId);
<div style="text-align: justify;">
YAHOO.extend(Alfresco.dashlet.SampleDashlet, Alfresco.component.Base,</div>
/**
* Extend from Alfresco.component.Base and add class implementation
*/
{
/**
<div style="text-align: justify;">
options:</div>
* Object container for initialization options
*
* @property options
* @type object
*/
{
},
<div style="text-align: justify;">
Event.addListener(this.id + "-link", "click", this.onLinkClick, this, true);</div>
onReady: function SampleDashlet_onReady()
{
var link = Dom.get(this.id + "-link");
console.log("Dashlet Ready");
<div style="text-align: justify;">
</div>
},
onLinkClick: function SampleDashlet_onLinkClick(e)
{
alert("Clicked...");
return false;
}
});
})();
<div style="text-align: justify;">
</div>
</pre>
<div class="separator" style="clear: both; text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
</div>
</div>
<div style="text-align: justify;">
<img height="177" src="https://s-media-cache-ak0.pinimg.com/originals/e2/84/4d/e2844d19244f0c0c767503482b9508b8.png" width="400" /></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Once user clicks on click me link.
<img src="https://s-media-cache-ak0.pinimg.com/originals/67/e6/e2/67e6e2bcd3761f00820d9c5a9ae9bf36.png" />
</div>
</div>
<div class="blogger-post-footer">https://scontent-b-mxp.xx.fbcdn.net/hphotos-xap1/v/t1.0-9/10675541_896261013719814_5601513019470361090_n.jpg?oh=741b05a81becaae8bce36db141948a4a&oe=5531762A</div>Krutik Jayswalhttp://www.blogger.com/profile/16691396948811505379noreply@blogger.comtag:blogger.com,1999:blog-2571457445842624811.post-13691036513133703282016-07-03T10:27:00.001-07:002016-07-03T10:27:02.122-07:00Hibernate and Relationship<div dir="ltr" style="text-align: left;" trbidi="on">
<div align="center" class="MsoNormal" style="text-align: center;">
<b><span lang="EN-US" style="background: white; color: #4f81bd; font-size: 22pt;">Hibernate<o:p></o:p></span></b></div>
<div class="MsoNormal">
<b><span lang="EN-US" style="background: white; color: #4f81bd; font-size: 14pt;">Introduction<o:p></o:p></span></b></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="background: white;">Hibernate is an Object-Relational Mapping(ORM) solution for JAVA and it raised as an open source persistent framework<span class="apple-converted-space"> .<o:p></o:p></span></span></div>
<div class="MsoNormal" style="background: white; margin: 9.6pt 0cm 12pt; text-align: justify;">
<span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial;">Hibernate maps Java classes to database tables and from Java data types to SQL data types and relieve the developer from 95% of common data persistence related programming tasks.<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; margin: 9.6pt 0cm 12pt; text-align: justify;">
<span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial;">Hibernate sits between traditional Java objects and database server to handle all the work in persisting those objects based on the appropriate O/R mechanisms and patterns.<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; margin: 9.6pt 0cm 12pt; text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-UkGNVG-iPGs/U566Tc8n0LI/AAAAAAAARq8/jQkvIZ21zG8/s1600/Hibernate_Position.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="217" src="https://1.bp.blogspot.com/-UkGNVG-iPGs/U566Tc8n0LI/AAAAAAAARq8/jQkvIZ21zG8/s1600/Hibernate_Position.jpg" width="640" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div align="center" class="MsoNormal" style="background: white; margin-bottom: 0.0001pt; text-align: center;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal">
<b><span lang="EN-US" style="background: white; color: #4f81bd; font-size: 14pt;"> Advantages:<o:p></o:p></span></b></div>
<div class="MsoListParagraphCxSpFirst" style="background: white; margin: 9.6pt 0cm 12pt 36pt; text-align: justify; text-indent: -18pt;">
<span style="font-family: "symbol";">·<span style="font-family: "times new roman"; font-size: 7pt;"> </span></span><span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial;">Hibernate takes care of mapping Java classes to database tables.<o:p></o:p></span></div>
<div class="MsoListParagraphCxSpMiddle" style="background: white; margin: 9.6pt 0cm 12pt 36pt; text-align: justify; text-indent: -18pt;">
<span style="font-family: "symbol";">·<span style="font-family: "times new roman"; font-size: 7pt;"> </span></span><span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial;">Provides simple APIs for storing and retrieving Java objects directly to and from the database.<o:p></o:p></span></div>
<div class="MsoListParagraphCxSpMiddle" style="background: white; margin: 9.6pt 0cm 12pt 36pt; text-align: justify; text-indent: -18pt;">
<span style="font-family: "symbol";">·<span style="font-family: "times new roman"; font-size: 7pt;"> </span></span><span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial;">Abstract away the unfamiliar SQL types and provide us to work around familiar Java Objects.<o:p></o:p></span></div>
<div class="MsoListParagraphCxSpMiddle" style="background: white; margin: 9.6pt 0cm 12pt 36pt; text-align: justify; text-indent: -18pt;">
<span style="font-family: "symbol";">·<span style="font-family: "times new roman"; font-size: 7pt;"> </span></span><span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial;">Manipulates Complex associations of objects of your database.<o:p></o:p></span></div>
<div class="MsoListParagraphCxSpMiddle" style="background: white; margin: 9.6pt 0cm 12pt 36pt; text-align: justify; text-indent: -18pt;">
<span style="font-family: "symbol";">·<span style="font-family: "times new roman"; font-size: 7pt;"> </span></span><span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial;">Minimize database access with smart fetching strategies.<o:p></o:p></span></div>
<div class="MsoListParagraphCxSpLast" style="background: white; margin: 9.6pt 0cm 12pt 36pt; text-align: justify; text-indent: -18pt;">
<span style="font-family: "symbol";">·<span style="font-family: "times new roman"; font-size: 7pt;"> </span></span><span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial;">Provides Simple querying of data.<o:p></o:p></span></div>
<div class="MsoNormal">
<b><span lang="EN-US" style="background: white; color: #4f81bd; font-size: 14pt;">Hibernate Architecture:<o:p></o:p></span></b></div>
<div class="MsoNormal" style="background: white; margin: 9.6pt 0cm 12pt; text-align: justify;">
<span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial;">The Hibernate architecture is layered to keep you isolated from having to know the underlying APIs. Hibernate makes use of the database and configuration data to provide persistence services (and persistent objects) to the application.<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; margin: 9.6pt 0cm 12pt; text-align: justify;">
<span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial;">Following is a very high level view of the Hibernat</span><span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial;">e</span><span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial;"> Application Architecture.<o:p></o:p></span></div>
<div align="center" class="MsoNormal" style="background: white; margin-bottom: 0.0001pt; text-align: center;">
<a href="http://4.bp.blogspot.com/-cqDnsgCjDDU/U566UraaLMI/AAAAAAAARrE/F5ekuMh8cTs/s1600/Hibernate_Architecture.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="594" src="https://4.bp.blogspot.com/-cqDnsgCjDDU/U566UraaLMI/AAAAAAAARrE/F5ekuMh8cTs/s1600/Hibernate_Architecture.jpg" width="640" /></a></div>
<div class="MsoNormal" style="background: white; margin: 9.6pt 0cm 12pt; text-align: justify;">
<span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial;">Following is a detailed view of the Hibernate Application Architecture with few important core classes.<o:p></o:p></span></div>
<div align="center" class="MsoNormal" style="background: white; margin-bottom: 0.0001pt; text-align: center;">
<a href="http://3.bp.blogspot.com/-KRFgLTSIeZE/U566XAA7_LI/AAAAAAAARrM/4kDPvH-cNY0/s1600/Hibernate_High_Level_Review.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="518" src="https://3.bp.blogspot.com/-KRFgLTSIeZE/U566XAA7_LI/AAAAAAAARrM/4kDPvH-cNY0/s1600/Hibernate_High_Level_Review.jpg" width="640" /></a></div>
<div class="MsoNormal" style="background: white; margin: 9.6pt 0cm 12pt; text-align: justify;">
<span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial;">Hibernate uses various existing Java APIs, like JDBC, Java Transaction API(JTA), and Java Naming and Directory Interface (JNDI). JDBC provides a rudimentary level of abstraction of functionality common to relational databases, allowing almost any database with a JDBC driver to be supported by Hibernate. JNDI and JTA allow Hibernate to be integrated with J2EE application servers. <o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; margin: 9.6pt 0cm 12pt; text-align: justify;">
<span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial;">Following section gives brief description of each of the class objects involved in Hibernate Application Architecture.<o:p></o:p></span></div>
<div class="MsoNormal">
<b><span lang="EN-US" style="background: white; color: #4f81bd; font-size: 14pt;">Configuration Object:<o:p></o:p></span></b></div>
<div class="MsoNormal" style="background: white; margin: 9.6pt 0cm 12pt; text-align: justify;">
<span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial;">The Configuration object is the first Hibernate object you create in any Hibernate application and usually created only once during application initialization. It represents a configuration or properties file required by the Hibernate. The Configuration object provides two keys components:<o:p></o:p></span></div>
<div class="MsoListParagraphCxSpFirst" style="background: white; margin-bottom: 0.0001pt; text-align: justify; text-indent: -18pt;">
<span style="font-family: "symbol";">·<span style="font-family: "times new roman"; font-size: 7pt;"> </span></span><span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial;">Database Connection: This is handled through one or more configuration files supported by Hibernate. These files are hibernate.properties and hibernate.cfg.xml.<o:p></o:p></span></div>
<div class="MsoListParagraphCxSpLast" style="background: white; margin-bottom: 0.0001pt; text-indent: -18pt;">
<span style="font-family: "symbol";">·<span style="font-family: "times new roman"; font-size: 7pt;"> </span></span><span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial;">Class Mapping Setup. This is achieved by using hbm.xml file or by Annotations.<br /><br /><o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; margin-bottom: 0.0001pt;">
<span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial;">This component creates the connection between the Java classes and database tables.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b><span lang="EN-US" style="background: white; color: #4f81bd; font-size: 14pt;">SessionFactory Object:<o:p></o:p></span></b></div>
<div class="MsoNormal" style="background: white; margin: 9.6pt 0cm 12pt; text-align: justify;">
<span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial;">Configuration object is used to create a SessionFactory object which intern configures Hibernate for the application using the supplied configuration file and allows for a Session object to be instantiated. The SessionFactory is a thread safe object and used by all the threads of an application.<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; margin: 9.6pt 0cm 12pt; text-align: justify;">
<span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial;">The SessionFactory is heavyweight object so usually it is created during application start up and kept for later use. You would need one SessionFactory object per database using a separate configuration file. So if you are using multiple databases then you would have to create multiple SessionFactory objects.<o:p></o:p></span></div>
<div class="MsoListParagraphCxSpFirst" style="margin-left: 54pt; text-indent: -18pt;">
<span style="font-family: "symbol";">·<span style="font-family: "times new roman"; font-size: 7pt;"> </span></span>Read</div>
<div class="MsoListParagraphCxSpMiddle" style="margin-left: 54pt; text-indent: -18pt;">
<span style="font-family: "symbol";">·<span style="font-family: "times new roman"; font-size: 7pt;"> </span></span>Check db</div>
<div class="MsoListParagraphCxSpMiddle" style="margin-left: 54pt; text-indent: -18pt;">
<span style="font-family: "symbol";">·<span style="font-family: "times new roman"; font-size: 7pt;"> </span></span>Connection into memory</div>
<div class="MsoListParagraphCxSpMiddle" style="margin-left: 54pt; text-indent: -18pt;">
<span style="font-family: "symbol";">·<span style="font-family: "times new roman"; font-size: 7pt;"> </span></span>Parse all hbm files</div>
<div class="MsoListParagraphCxSpLast" style="margin-left: 54pt; text-indent: -18pt;">
<span style="font-family: "symbol";">·<span style="font-family: "times new roman"; font-size: 7pt;"> </span></span>Corresponding tables exist</div>
<div class="MsoNormal">
<b><span lang="EN-US" style="background: white; color: #4f81bd; font-size: 14pt;">Session Object:<o:p></o:p></span></b></div>
<div class="MsoNormal" style="background: white; margin: 9.6pt 0cm 12pt; text-align: justify;">
<span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial;">A Session is used to get a physical connection with a database. The Session object is lightweight and designed to be instantiated each time an interaction is needed with the database. Persistent objects are saved and retrieved through a Session object.<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; margin: 9.6pt 0cm 12pt; text-align: justify;">
<span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial;">The session objects should not be kept open for a long time because they are not usually thread safe and they should be created and destroyed them as needed.<o:p></o:p></span></div>
<div class="MsoNormal">
<b><span lang="EN-US" style="background: white; color: #4f81bd; font-size: 14pt;">Transaction Object:<o:p></o:p></span></b></div>
<div class="MsoNormal" style="background: white; margin: 9.6pt 0cm 12pt; text-align: justify;">
<span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial;">A Transaction represents a unit of work with the database and most of the RDBMS supports transaction functionality. Transactions in Hibernate are handled by an underlying transaction manager and transaction (from JDBC or JTA).<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; margin: 9.6pt 0cm 12pt; text-align: justify;">
<span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial;">This is an optional object and Hibernate applications may choose not to use this interface, instead managing transactions in their own application code.<o:p></o:p></span></div>
<div class="MsoNormal">
<b><span lang="EN-US" style="background: white; color: #4f81bd; font-size: 14pt;">Query Object:<o:p></o:p></span></b></div>
<div class="MsoNormal" style="background: white; margin: 9.6pt 0cm 12pt; text-align: justify;">
<span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial;">Query objects use SQL or Hibernate Query Language (HQL) string to retrieve data from the database and create objects. A Query instance is used to bind query parameters, limit the number of results returned by the query, and finally to execute the query.<o:p></o:p></span></div>
<div class="MsoNormal">
<b><span lang="EN-US" style="background: white; color: #4f81bd; font-size: 14pt;">Criteria Object:<o:p></o:p></span></b></div>
<div class="MsoNormal" style="background: white; margin: 9.6pt 0cm 12pt; text-align: justify;">
<span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial;">Criteria object are used to create and execute object oriented criteria queries to retrieve objects.<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; margin: 9.6pt 0cm 12pt; text-align: justify;">
<b><span lang="EN-US" style="color: #4f81bd; font-size: 14pt;">Hibernate Relationships:<o:p></o:p></span></b></div>
<div class="MsoNormal" style="background: white; margin: 9.6pt 0cm 12pt; text-align: justify;">
<span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial;">Using hibernate, if we want to put relationship between two entities [objects of two pojo classes], then in the database tables, there must exist foreign key relationship, we call it as Referential integrity.<o:p></o:p></span></div>
<div class="MsoNormal">
<b><span lang="EN-US" style="background: white; color: #4f81bd; font-size: 14pt;">One-To-One<o:p></o:p></span></b></div>
<div class="MsoNormal" style="background: white; margin: 9.6pt 0cm 12pt; text-align: justify;">
<span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #3c3c3c; font-family: "arial" , sans-serif;">A one-to-one relationship occurs when one entity is related to exactly one occurrence in another entity.<o:p></o:p></span></div>
<div style="background: rgb(245, 245, 245); border: 1pt solid rgb(204, 204, 204); margin-left: 21.3pt; margin-right: 0cm; padding: 4pt 11pt 4pt 19pt;">
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="font-size: 11pt;">@</span></span><span class="javatype"><span style="font-size: 11pt;">Entity</span></span><span style="color: #333333; font-size: 11pt;"><o:p></o:p></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javakeyword"><b><span style="color: #7f1b55; font-size: 11pt;">public</span></b></span><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javakeyword"><b><span style="color: #7f1b55; font-size: 11pt;">class</span></b></span><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javatype"><span style="font-size: 11pt;">Body</span></span><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javaseparator"><span style="font-size: 11pt;">{</span></span><span style="color: #333333; font-size: 11pt;"><o:p></o:p></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="font-size: 11pt;"> @</span></span><span class="javatype"><span style="font-size: 11pt;">Id</span></span><span style="color: #333333; font-size: 11pt;"><o:p></o:p></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javakeyword"><b><span style="color: #7f1b55; font-size: 11pt;">private</span></b></span><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javatype"><span style="font-size: 11pt;">Long</span></span><span class="javaplain"><span style="font-size: 11pt;"> id</span></span><span class="javaseparator"><span style="font-size: 11pt;">;</span></span><span style="color: #333333; font-size: 11pt;"><o:p></o:p></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span style="color: #333333; font-size: 11pt;"> </span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="font-size: 11pt;"> @</span></span><span class="javatype"><span style="font-size: 11pt;">OneToOne</span></span><span class="javaseparator"><span style="font-size: 11pt;">(</span></span><span class="javaplain"><span style="font-size: 11pt;">cascade </span></span><span class="javaoperator"><span style="font-size: 11pt;">=</span></span><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javatype"><span style="font-size: 11pt;">CascadeType</span></span><span class="javaseparator"><span style="font-size: 11pt;">.</span></span><span class="javaplain"><span style="font-size: 11pt;">ALL</span></span><span class="javaseparator"><span style="font-size: 11pt;">)</span></span><span style="color: #333333; font-size: 11pt;"><o:p></o:p></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="font-size: 11pt;"> @</span></span><span class="javatype"><span style="font-size: 11pt;">PrimaryKeyJoinColumn</span></span><span style="color: #333333; font-size: 11pt;"><o:p></o:p></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javakeyword"><b><span style="color: #7f1b55; font-size: 11pt;">private</span></b></span><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javatype"><span style="font-size: 11pt;">Heart</span></span><span class="javaplain"><span style="font-size: 11pt;"> heart;</span></span><span style="color: #333333; font-size: 11pt;"><o:p></o:p></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span style="color: #333333; font-size: 11pt;"> </span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javaseparator"><span style="font-size: 11pt;">...</span></span><span style="color: #333333; font-size: 11pt;"><o:p></o:p></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaseparator"><span style="font-size: 11pt;">}</span></span><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span style="color: #333333; font-size: 11pt;"><o:p></o:p></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="font-size: 11pt;">@</span></span><span class="javatype"><span style="font-size: 11pt;">Entity</span></span><span style="color: #333333; font-size: 11pt;"><o:p></o:p></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javakeyword"><b><span style="color: #7f1b55; font-size: 11pt;">public</span></b></span><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javakeyword"><b><span style="color: #7f1b55; font-size: 11pt;">class</span></b></span><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javatype"><span style="font-size: 11pt;">Heart</span></span><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javaseparator"><span style="font-size: 11pt;">{</span></span><span style="color: #333333; font-size: 11pt;"><o:p></o:p></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="font-size: 11pt;"> @</span></span><span class="javatype"><span style="font-size: 11pt;">Id</span></span><span style="color: #333333; font-size: 11pt;"><o:p></o:p></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javakeyword"><b><span style="color: #7f1b55; font-size: 11pt;">public</span></b></span><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javatype"><span style="font-size: 11pt;">Long</span></span><span class="javaplain"><span style="font-size: 11pt;"> getId</span></span><span class="javaseparator"><span style="font-size: 11pt;">()</span></span><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javaseparator"><span style="font-size: 11pt;">{</span></span><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javaseparator"><span style="font-size: 11pt;">...}</span></span><span style="color: #333333; font-size: 11pt;"><o:p></o:p></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaseparator"><span style="font-size: 11pt;">}</span></span><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span style="color: #333333; font-size: 11pt;"><o:p></o:p></span></pre>
</div>
<h4 style="line-height: 12pt; margin-top: 0cm; text-align: justify;">
<span style="color: #4a5d75; font-family: "verdana" , "sans-serif"; font-size: 10pt;"> </span></h4>
<div class="MsoNormal">
<b><span lang="EN-US" style="background: white; color: #4f81bd; font-size: 14pt;">One-To-Many <o:p></o:p></span></b></div>
<div class="MsoNormal">
<span style="color: #333333; font-family: "verdana" , "sans-serif"; font-size: 9pt;">It is a type of relationship in which each record in one table is linked to multiple records in another table.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div style="background: rgb(245, 245, 245); border: 1pt solid rgb(204, 204, 204); margin-left: 21.3pt; margin-right: 0cm; padding: 4pt 11pt 4pt 19pt;">
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="font-size: 11pt;">@</span></span><span class="javatype"><span style="font-size: 11pt;">Entity</span></span><span style="color: #333333; font-size: 11pt;"><o:p></o:p></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javakeyword"><b><span style="color: #7f1b55; font-size: 11pt;">public</span></b></span><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javakeyword"><b><span style="color: #7f1b55; font-size: 11pt;">class</span></b></span><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javatype"><span style="font-size: 11pt;">Troop</span></span><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javaseparator"><span style="font-size: 11pt;">{</span></span><span style="color: #333333; font-size: 11pt;"><o:p></o:p></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javaplain"><span style="color: #4f81bd; font-size: 11pt;">@</span></span><span class="javatype"><span style="color: #4f81bd; font-size: 11pt;">OneToMany</span></span><span class="javaseparator"><span style="color: #4f81bd; font-size: 11pt;">(</span></span><span class="javaplain"><span style="color: #4f81bd; font-size: 11pt;">mappedBy</span></span><span class="javaoperator"><span style="color: #4f81bd; font-size: 11pt;">=</span></span><span class="javaliteral"><span style="color: #4f81bd; font-size: 11pt;">"troop"</span></span><span class="javaseparator"><span style="color: #4f81bd; font-size: 11pt;">)</span></span><span style="color: #4f81bd; font-size: 11pt;"><o:p></o:p></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javakeyword"><b><span style="color: #7f1b55; font-size: 11pt;">private</span></b></span><span class="javaplain"><span style="font-size: 11pt;"> Set<Soilder> soldiers;</span></span><span style="color: #333333; font-size: 11pt;"><o:p></o:p></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javaseparator"><span style="font-size: 11pt;">... </span></span><span style="color: #333333; font-size: 11pt;"><o:p></o:p></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaseparator"><span style="font-size: 11pt;">}</span></span><span style="color: #333333; font-size: 11pt;"><o:p></o:p></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span style="color: #333333; font-size: 11pt;"> </span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="font-size: 11pt;">@</span></span><span class="javatype"><span style="font-size: 11pt;">Entity</span></span><span style="color: #333333; font-size: 11pt;"><o:p></o:p></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javakeyword"><b><span style="color: #7f1b55; font-size: 11pt;">public</span></b></span><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javakeyword"><b><span style="color: #7f1b55; font-size: 11pt;">class</span></b></span><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javatype"><span style="font-size: 11pt;">Soldier</span></span><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javaseparator"><span style="font-size: 11pt;">{</span></span><span style="color: #333333; font-size: 11pt;"><o:p></o:p></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="color: #4f81bd; font-size: 11pt;"> @</span></span><span class="javatype"><span style="color: #4f81bd; font-size: 11pt;">ManyToOne </span></span><span style="color: #4f81bd; font-size: 11pt;"><o:p></o:p></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="color: #4f81bd; font-size: 11pt;"> @</span></span><span class="javatype"><span style="color: #4f81bd; font-size: 11pt;">JoinColumn</span></span><span class="javaseparator"><span style="color: #4f81bd; font-size: 11pt;">(</span></span><span class="javaplain"><span style="color: #4f81bd; font-size: 11pt;">name</span></span><span class="javaoperator"><span style="color: #4f81bd; font-size: 11pt;">=</span></span><span class="javaliteral"><span style="color: #4f81bd; font-size: 11pt;">"troop_fk"</span></span><span class="javaseparator"><span style="color: #4f81bd; font-size: 11pt;">)</span></span><span style="color: #4f81bd; font-size: 11pt;"><o:p></o:p></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javakeyword"><b><span style="color: #7f1b55; font-size: 11pt;">Private </span></b></span><span class="javatype"><span style="font-size: 11pt;">Troop</span></span><span class="javaplain"><span style="font-size: 11pt;"> troop</span></span><span class="javaseparator"><span style="font-size: 11pt;">;</span></span><span style="color: #333333; font-size: 11pt;"><o:p></o:p></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javaseparator"><span style="font-size: 11pt;">...</span></span><span style="color: #333333; font-size: 11pt;"><o:p></o:p></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaseparator"><span style="font-size: 11pt;">}</span></span><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span style="color: #333333; font-size: 11pt;"><o:p></o:p></span></pre>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b><span lang="EN-US" style="background: white; color: #4f81bd; font-size: 14pt;">Many-to-one <o:p></o:p></span></b></div>
<div style="line-height: 13.5pt; text-align: justify;">
<span style="color: #333333; font-family: "verdana" , "sans-serif"; font-size: 9pt;">Many-to-one associations are declared at the property level with the annotation</span><span class="apple-converted-space"><span style="color: #333333; font-family: "verdana" , "sans-serif"; font-size: 9pt;"> </span></span><code><span style="color: #333333; font-family: "verdana" , "sans-serif"; font-size: 10pt;">@ManyToOne</span></code><span style="color: #333333; font-family: "verdana" , "sans-serif"; font-size: 9pt;">:<o:p></o:p></span></div>
<div style="background: rgb(245, 245, 245); border: 1pt solid rgb(204, 204, 204); margin-left: 21.3pt; margin-right: 0cm; padding: 4pt 11pt 4pt 19pt;">
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="font-size: 11pt;">@</span></span><span class="javatype"><span style="font-size: 11pt;">Entity</span></span><span style="color: #333333; font-size: 11pt;"><o:p></o:p></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javakeyword"><b><span style="color: #7f1b55; font-size: 11pt;">public</span></b></span><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javakeyword"><b><span style="color: #7f1b55; font-size: 11pt;">class</span></b></span><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javatype"><span style="font-size: 11pt;">Flight</span></span><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javakeyword"><b><span style="color: #7f1b55; font-size: 11pt;">implements</span></b></span><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javatype"><span style="font-size: 11pt;">Serializable</span></span><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javaseparator"><span style="font-size: 11pt;">{</span></span><span style="color: #333333; font-size: 11pt;"><o:p></o:p></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="font-size: 11pt;"> <o:p></o:p></span></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="color: #4f81bd; font-size: 11pt;"> @</span></span><span class="javatype"><span style="color: #4f81bd; font-size: 11pt;">ManyToOne</span></span><span class="javaseparator"><span style="color: #4f81bd; font-size: 11pt;">(</span></span><span class="javaplain"><span style="color: #4f81bd; font-size: 11pt;"> cascade </span></span><span class="javaoperator"><span style="color: #4f81bd; font-size: 11pt;">=</span></span><span class="javaplain"><span style="color: #4f81bd; font-size: 11pt;"> </span></span><span class="javaseparator"><span style="color: #4f81bd; font-size: 11pt;">{</span></span><span class="javatype"><span style="color: #4f81bd; font-size: 11pt;">CascadeType</span></span><span class="javaseparator"><span style="color: #4f81bd; font-size: 11pt;">.</span></span><span class="javaplain"><span style="color: #4f81bd; font-size: 11pt;">PERSIST</span></span><span class="javaseparator"><span style="color: #4f81bd; font-size: 11pt;">,</span></span><span class="javaplain"><span style="color: #4f81bd; font-size: 11pt;"> </span></span><span class="javatype"><span style="color: #4f81bd; font-size: 11pt;">CascadeType</span></span><span class="javaseparator"><span style="color: #4f81bd; font-size: 11pt;">.</span></span><span class="javaplain"><span style="color: #4f81bd; font-size: 11pt;">MERGE</span></span><span class="javaseparator"><span style="color: #4f81bd; font-size: 11pt;">}</span></span><span class="javaplain"><span style="color: #4f81bd; font-size: 11pt;"> </span></span><span class="javaseparator"><span style="color: #4f81bd; font-size: 11pt;">)</span></span><span style="color: #4f81bd; font-size: 11pt;"><o:p></o:p></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="color: #4f81bd; font-size: 11pt;"> @</span></span><span class="javatype"><span style="color: #4f81bd; font-size: 11pt;">JoinColumn</span></span><span class="javaseparator"><span style="color: #4f81bd; font-size: 11pt;">(</span></span><span class="javaplain"><span style="color: #4f81bd; font-size: 11pt;">name</span></span><span class="javaoperator"><span style="color: #4f81bd; font-size: 11pt;">=</span></span><span class="javaliteral"><span style="color: #4f81bd; font-size: 11pt;">"COMP_ID"</span></span><span class="javaseparator"><span style="color: #4f81bd; font-size: 11pt;">)</span></span><span style="color: #4f81bd; font-size: 11pt;"><o:p></o:p></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javakeyword"><b><span style="color: #7f1b55; font-size: 11pt;">private </span></b></span><span class="javatype"><span style="font-size: 11pt;">Company</span></span><span class="javaplain"><span style="font-size: 11pt;"> company</span></span><span class="javaseparator"><span style="font-size: 11pt;">();</span></span><span style="color: #333333; font-size: 11pt;"><o:p></o:p></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javaseparator"><span style="font-size: 11pt;">...</span></span><span style="color: #333333; font-size: 11pt;"><o:p></o:p></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaseparator"><span style="font-size: 11pt;">}</span></span><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span style="color: #333333; font-size: 11pt;"><o:p></o:p></span></pre>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b><span lang="EN-US" style="background: white; color: #4f81bd; font-size: 14pt;">Many-to-Many <o:p></o:p></span></b></div>
<div class="MsoNormal" style="background: white; margin: 9.6pt 0cm 12pt; text-align: justify;">
<span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial;">It is a logical data relationship in which the value of one data element can exist in combination with many values of another data element, and vice versa.<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; margin: 9.6pt 0cm 12pt; text-align: justify;">
<br /></div>
<div style="background: rgb(245, 245, 245); border: 1pt solid rgb(204, 204, 204); margin-left: 21.3pt; margin-right: 0cm; padding: 4pt 11pt 4pt 19pt;">
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="font-size: 11pt;">@Entity<o:p></o:p></span></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="font-size: 11pt;">@Table(name="EMPLOYEE")<o:p></o:p></span></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javakeyword"><b><span style="color: #7f1b55; font-size: 11pt;">public</span></b></span><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javakeyword"><b><span style="color: #7f1b55; font-size: 11pt;">class</span></b></span><span class="javaplain"><span style="font-size: 11pt;"> Employee { <o:p></o:p></span></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javaplain"><span style="color: #4f81bd; font-size: 11pt;">@ManyToMany(cascade = {CascadeType.ALL})<o:p></o:p></span></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="color: #4f81bd; font-size: 11pt;"> @JoinTable(name="EMPLOYEE_MEETING", <o:p></o:p></span></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="color: #4f81bd; font-size: 11pt;"> joinColumns={@JoinColumn(name="EMPLOYEE_ID")}, <o:p></o:p></span></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="color: #4f81bd; font-size: 11pt;"> inverseJoinColumns={@JoinColumn(name="MEETING_ID")})<o:p></o:p></span></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javakeyword"><b><span style="color: #7f1b55;">private </span></b></span><span class="javaplain"><span style="font-size: 11pt;">Set<Meeting> meetings = new HashSet<Meeting>();<o:p></o:p></span></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="font-size: 11pt;"> ...<o:p></o:p></span></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="font-size: 11pt;">}<o:p></o:p></span></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="font-size: 11pt;">@Entity<o:p></o:p></span></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="font-size: 11pt;">@Table(name="MEETING")<o:p></o:p></span></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javakeyword"><b><span style="color: #7f1b55;">public class</span></b></span><span class="javaplain"><span style="font-size: 11pt;"> Meeting { <o:p></o:p></span></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="color: #4f81bd; font-size: 11pt;"> @ManyToMany(mappedBy="meetings")<o:p></o:p></span></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javaplain"><span style="font-size: 11pt;"> </span></span><span class="javakeyword"><b><span style="color: #7f1b55;">private </span></b></span><span class="javaplain"><span style="font-size: 11pt;">Set<Employee> employees = new HashSet<Employee>();<o:p></o:p></span></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javakeyword"><b><span style="color: #7f1b55;"> ...<o:p></o:p></span></b></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span class="javakeyword"><b><span style="color: #7f1b55;">}<o:p></o:p></span></b></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; line-height: 15.5pt; padding: 0cm; text-align: justify;"><span style="color: #333333; font-size: 11pt;"> </span></pre>
</div>
<div class="MsoNormal" style="background: white; margin: 9.6pt 0cm 12pt; text-align: justify;">
<br /></div>
<div class="MsoNormal">
<b><span lang="EN-US" style="background: white; color: #4f81bd; font-size: 14pt;">Hibernate Annotations:<o:p></o:p></span></b></div>
<div class="MsoNormal">
<b><span lang="EN-US" style="background: white; color: #4f81bd; font-size: 14pt;">@Entity<o:p></o:p></span></b></div>
<div class="MsoNormal">
<span style="background: white;">This annotations is used to mark a class as an Entity bean.<o:p></o:p></span></div>
<div class="MsoNormal">
<b><span lang="EN-US" style="background: white; color: #4f81bd; font-size: 14pt;">@Table<o:p></o:p></span></b></div>
<div style="background: white; margin: 9.6pt 0cm 12pt; text-align: justify;">
<span style="font-family: "calibri" , sans-serif; font-size: 11pt;">The @Table annotation allows you to specify the details of the table that will be used to persist the entity in the database.<o:p></o:p></span></div>
<div class="MsoNormal">
<b><span lang="EN-US" style="background: white; color: #4f81bd; font-size: 14pt;">@ID and @Generated Value<o:p></o:p></span></b></div>
<div style="background: white; margin: 0cm; text-align: justify;">
<span style="font-family: "calibri" , sans-serif; font-size: 11pt;">Each entity bean will have a primary key, which you annotate on the class with the</span><span style="font-family: "calibri" , sans-serif; font-size: 11pt;"> @Id annotation. The primary key can be a single field or a combination of multiple fields depending on your table structure.<o:p></o:p></span></div>
<div style="background: white; margin: 0cm; text-align: justify;">
<span style="font-family: "calibri" , sans-serif; font-size: 11pt;">By default, the @Id annotation will automatically determine the most appropriate primary key generation strategy to be used but you can override this by applying the</span><span style="font-family: "calibri" , sans-serif; font-size: 11pt;"> @GeneratedValue annotation which takes two parameters strategy and generator. Preferred way is to use only default the default key generation strategy. Letting Hibernate determine which generator type to use makes your code portable between different databases.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b><span lang="EN-US" style="background: white; color: #4f81bd; font-size: 14pt;">@Column<o:p></o:p></span></b></div>
<div style="background: white; margin: 9.6pt 0cm 12pt; text-align: justify;">
<span style="font-family: "calibri" , sans-serif; font-size: 11pt;">The @Column annotation is used to specify the details of the column to which a field or property will be mapped. You can use column annotation with the following most commonly used attributes:<o:p></o:p></span></div>
<div style="background: white; margin: 0cm 0cm 0cm 36pt; text-align: justify; text-indent: -18pt;">
<span style="font-family: "symbol"; font-size: 11pt;">·<span style="font-family: "times new roman"; font-size: 7pt;"> </span></span><b><span style="font-family: "calibri" , sans-serif; font-size: 11pt;">name</span></b><span style="font-family: "calibri" , sans-serif; font-size: 11pt;"> attribute permits the name of the column to be explicitly specified.<o:p></o:p></span></div>
<div style="background: white; margin: 0cm 0cm 0cm 36pt; text-align: justify; text-indent: -18pt;">
<span style="font-family: "symbol"; font-size: 11pt;">·<span style="font-family: "times new roman"; font-size: 7pt;"> </span></span><b><span style="font-family: "calibri" , sans-serif; font-size: 11pt;">length</span></b><span style="font-family: "calibri" , sans-serif; font-size: 11pt;"> attribute permits the size of the column used to map a value particularly for a String value.<o:p></o:p></span></div>
<div style="background: white; margin: 0cm 0cm 0cm 36pt; text-align: justify; text-indent: -18pt;">
<span style="font-family: "symbol"; font-size: 11pt;">·<span style="font-family: "times new roman"; font-size: 7pt;"> </span></span><b><span style="font-family: "calibri" , sans-serif; font-size: 11pt;">nullable</span></b><span style="font-family: "calibri" , sans-serif; font-size: 11pt;"> attribute permits the column to be marked NOT NULL when the schema is generated.<o:p></o:p></span></div>
<div style="background: white; margin: 0cm 0cm 0cm 36pt; text-align: justify; text-indent: -18pt;">
<span style="font-family: "symbol"; font-size: 11pt;">·<span style="font-family: "times new roman"; font-size: 7pt;"> </span></span><b><span style="font-family: "calibri" , sans-serif; font-size: 11pt;">unique</span></b><span style="font-family: "calibri" , sans-serif; font-size: 11pt;"> attribute permits the column to be marked as containing only unique values.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b><span lang="EN-US" style="background: white; color: #4f81bd; font-size: 14pt;">Example:<o:p></o:p></span></b></div>
<br />
<div style="background: rgb(238, 238, 238); border: 1pt solid rgb(214, 214, 214); margin-left: 7.1pt; margin-right: 0cm; padding: 4pt;">
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="color: #006666; font-family: "courier new"; font-size: 9pt;">@Entity</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="color: #006666; font-family: "courier new"; font-size: 9pt;">@Table</span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">(</span><span style="font-family: "courier new"; font-size: 9pt;">name </span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">=</span><span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #008800; font-family: "courier new"; font-size: 9pt;">"EMPLOYEE"</span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">)</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="color: #000088; font-family: "courier new"; font-size: 9pt;">public</span><span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #000088; font-family: "courier new"; font-size: 9pt;">class</span><span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #7f0055; font-family: "courier new"; font-size: 9pt;">Employee</span><span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">{</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #006666; font-family: "courier new"; font-size: 9pt;">@Id</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #006666; font-family: "courier new"; font-size: 9pt;">@GeneratedValue</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #006666; font-family: "courier new"; font-size: 9pt;">@Column</span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">(</span><span style="font-family: "courier new"; font-size: 9pt;">name </span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">=</span><span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #008800; font-family: "courier new"; font-size: 9pt;">"id"</span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">)</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #000088; font-family: "courier new"; font-size: 9pt;">private</span><span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #000088; font-family: "courier new"; font-size: 9pt;">int</span><span style="font-family: "courier new"; font-size: 9pt;"> id</span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">;</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<br /></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #006666; font-family: "courier new"; font-size: 9pt;">@Column</span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">(</span><span style="font-family: "courier new"; font-size: 9pt;">name </span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">=</span><span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #008800; font-family: "courier new"; font-size: 9pt;">"first_name"</span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">)</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #000088; font-family: "courier new"; font-size: 9pt;">private</span><span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #7f0055; font-family: "courier new"; font-size: 9pt;">String</span><span style="font-family: "courier new"; font-size: 9pt;"> firstName</span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">;</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<br /></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #006666; font-family: "courier new"; font-size: 9pt;">@Column</span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">(</span><span style="font-family: "courier new"; font-size: 9pt;">name </span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">=</span><span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #008800; font-family: "courier new"; font-size: 9pt;">"last_name"</span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">)</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #000088; font-family: "courier new"; font-size: 9pt;">private</span><span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #7f0055; font-family: "courier new"; font-size: 9pt;">String</span><span style="font-family: "courier new"; font-size: 9pt;"> lastName</span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">;</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<br /></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #006666; font-family: "courier new"; font-size: 9pt;">@Column</span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">(</span><span style="font-family: "courier new"; font-size: 9pt;">name </span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">=</span><span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #008800; font-family: "courier new"; font-size: 9pt;">"salary"</span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">)</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #000088; font-family: "courier new"; font-size: 9pt;">private</span><span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #000088; font-family: "courier new"; font-size: 9pt;">int</span><span style="font-family: "courier new"; font-size: 9pt;"> salary</span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">;</span><span style="font-family: "courier new"; font-size: 9pt;"> <o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<br /></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #000088; font-family: "courier new"; font-size: 9pt;">public</span><span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #7f0055; font-family: "courier new"; font-size: 9pt;">Employee</span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">()</span><span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">{}</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #000088; font-family: "courier new"; font-size: 9pt;">public</span><span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #000088; font-family: "courier new"; font-size: 9pt;">int</span><span style="font-family: "courier new"; font-size: 9pt;"> getId</span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">()</span><span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">{</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #000088; font-family: "courier new"; font-size: 9pt;">return</span><span style="font-family: "courier new"; font-size: 9pt;"> id</span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">;</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">}</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #000088; font-family: "courier new"; font-size: 9pt;">public</span><span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #000088; font-family: "courier new"; font-size: 9pt;">void</span><span style="font-family: "courier new"; font-size: 9pt;"> setId</span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">(</span><span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #000088; font-family: "courier new"; font-size: 9pt;">int</span><span style="font-family: "courier new"; font-size: 9pt;"> id </span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">)</span><span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">{</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #000088; font-family: "courier new"; font-size: 9pt;">this</span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">.</span><span style="font-family: "courier new"; font-size: 9pt;">id </span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">=</span><span style="font-family: "courier new"; font-size: 9pt;"> id</span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">;</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">}</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #000088; font-family: "courier new"; font-size: 9pt;">public</span><span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #7f0055; font-family: "courier new"; font-size: 9pt;">String</span><span style="font-family: "courier new"; font-size: 9pt;"> getFirstName</span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">()</span><span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">{</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #000088; font-family: "courier new"; font-size: 9pt;">return</span><span style="font-family: "courier new"; font-size: 9pt;"> firstName</span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">;</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">}</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #000088; font-family: "courier new"; font-size: 9pt;">public</span><span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #000088; font-family: "courier new"; font-size: 9pt;">void</span><span style="font-family: "courier new"; font-size: 9pt;"> setFirstName</span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">(</span><span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #7f0055; font-family: "courier new"; font-size: 9pt;">String</span><span style="font-family: "courier new"; font-size: 9pt;"> first_name </span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">)</span><span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">{</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #000088; font-family: "courier new"; font-size: 9pt;">this</span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">.</span><span style="font-family: "courier new"; font-size: 9pt;">firstName </span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">=</span><span style="font-family: "courier new"; font-size: 9pt;"> first_name</span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">;</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">}</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #000088; font-family: "courier new"; font-size: 9pt;">public</span><span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #7f0055; font-family: "courier new"; font-size: 9pt;">String</span><span style="font-family: "courier new"; font-size: 9pt;"> getLastName</span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">()</span><span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">{</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #000088; font-family: "courier new"; font-size: 9pt;">return</span><span style="font-family: "courier new"; font-size: 9pt;"> lastName</span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">;</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">}</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #000088; font-family: "courier new"; font-size: 9pt;">public</span><span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #000088; font-family: "courier new"; font-size: 9pt;">void</span><span style="font-family: "courier new"; font-size: 9pt;"> setLastName</span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">(</span><span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #7f0055; font-family: "courier new"; font-size: 9pt;">String</span><span style="font-family: "courier new"; font-size: 9pt;"> last_name </span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">)</span><span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">{</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #000088; font-family: "courier new"; font-size: 9pt;">this</span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">.</span><span style="font-family: "courier new"; font-size: 9pt;">lastName </span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">=</span><span style="font-family: "courier new"; font-size: 9pt;"> last_name</span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">;</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">}</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #000088; font-family: "courier new"; font-size: 9pt;">public</span><span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #000088; font-family: "courier new"; font-size: 9pt;">int</span><span style="font-family: "courier new"; font-size: 9pt;"> getSalary</span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">()</span><span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">{</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #000088; font-family: "courier new"; font-size: 9pt;">return</span><span style="font-family: "courier new"; font-size: 9pt;"> salary</span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">;</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">}</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #000088; font-family: "courier new"; font-size: 9pt;">public</span><span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #000088; font-family: "courier new"; font-size: 9pt;">void</span><span style="font-family: "courier new"; font-size: 9pt;"> setSalary</span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">(</span><span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #000088; font-family: "courier new"; font-size: 9pt;">int</span><span style="font-family: "courier new"; font-size: 9pt;"> salary </span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">)</span><span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">{</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #000088; font-family: "courier new"; font-size: 9pt;">this</span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">.</span><span style="font-family: "courier new"; font-size: 9pt;">salary </span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">=</span><span style="font-family: "courier new"; font-size: 9pt;"> salary</span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">;</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="font-family: "courier new"; font-size: 9pt;"> </span><span style="color: #666600; font-family: "courier new"; font-size: 9pt;">}</span><span style="font-family: "courier new"; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin-bottom: 0.0001pt; padding: 0cm;">
<span style="color: #666600; font-family: "courier new"; font-size: 9pt;">}</span></div>
</div>
</div>
<div class="blogger-post-footer">https://scontent-b-mxp.xx.fbcdn.net/hphotos-xap1/v/t1.0-9/10675541_896261013719814_5601513019470361090_n.jpg?oh=741b05a81becaae8bce36db141948a4a&oe=5531762A</div>Krutik Jayswalhttp://www.blogger.com/profile/16691396948811505379noreply@blogger.comtag:blogger.com,1999:blog-2571457445842624811.post-59798271026307019252015-07-13T04:13:00.001-07:002020-02-06T22:52:55.979-08:00Sending HTML mail for site invitation(alfresco 3.4d)<div dir="ltr" style="text-align: left;" trbidi="on">
You may have read my previous blog of <a href="http://krutikjayswal.blogspot.in/2015/07/html-mail-action-in-alfresco34d.html">Html Mail Action</a> inside alfresco 3.4d.If you have not read this , than before continuing with this you need to read that blog.<br />
<br />
Below is the screen shot of site invitation page in alfresco using which we can invite user to join site.<br />
<br />
<a href="https://lh3.googleusercontent.com/-P22hYUd-cHc/V8CdeI5jHYI/AAAAAAAATK4/PEnYZHZA5pg2FXwcQCz6zeILSLtf4BpoQCK4B/s1600/Screen%2BShot%2B2016-08-27%2Bat%2B1.19.56%2BAM.png" imageanchor="1"><img border="0" height="354" src="https://lh3.googleusercontent.com/-P22hYUd-cHc/V8CdeI5jHYI/AAAAAAAATK4/PEnYZHZA5pg2FXwcQCz6zeILSLtf4BpoQCK4B/s640/Screen%2BShot%2B2016-08-27%2Bat%2B1.19.56%2BAM.png" width="640" /></a><br />
<br />
Normally if we want to change site invitation template , than we need to modify <i>invite-email.ftl</i> file which is located at <i>/Data Dictionary/Email Templates/invite</i> location.Now as you all know for adding HTML content inside any templates in alfresco the custom action should support HTML content.Previously we have created an action which supports HTML content.Now in this case for site invitation it executes in built mail action, which does not supports html content.For this we need to modify site invitation workflow so that it executes customized mail action.
<br />
Follow below steps for that.
<br />
<br />
<br />
<b>Step 1 : Customize Site Invitation Workflow</b><br />
File which needs to be customized for modifying this workflow is located on below location <i>tomcat/webapps/alfresco/WEB-INF/classes/alfresco/workflow/invitation-nominated_processdefinition.xml</i>.Content of that file is as below.
<br />
<pre class="brush: xml" name="code"><!-- Nominated invitation -->
<process-definition name="inwf:invitation-nominated" xmlns="urn:jbpm.org:jpdl-3.1">
<swimlane name="initiator">
<start-state name="start">
<task name="inwf:inviteToSiteTask" swimlane="initiator">
<transition name="sendInvite" to="invitePending">
<action class="org.alfresco.repo.invitation.site.ds.SendInviteAction">
</action></transition>
</task></start-state>
<swimlane name="assignee">
<assignment class="org.alfresco.repo.workflow.jbpm.AlfrescoAssignment">
<actor>#{bpm_assignee.properties['cm:userName']}</actor>
</assignment>
</swimlane>
<task-node name="invitePending">
<task name="inwf:invitePendingTask" swimlane="assignee">
<transition name="accept" to="inviteAccepted">
<action class="org.alfresco.repo.invitation.site.AcceptInviteAction">
</action></transition>
<transition name="reject" to="inviteRejected">
<action class="org.alfresco.repo.invitation.site.RejectInviteAction">
</action></transition>
<transition name="cancel" to="end">
<action class="org.alfresco.repo.invitation.site.CancelInviteAction">
</action></transition>
</task></task-node>
<task-node name="inviteAccepted">
<task name="inwf:acceptInviteTask" swimlane="initiator">
<transition name="end" to="end">
</transition></task></task-node>
<task-node name="inviteRejected">
<task name="inwf:rejectInviteTask" swimlane="initiator">
<transition name="end" to="end">
</transition></task></task-node>
<end-state name="end">
</end-state></swimlane></process-definition>
</pre>
In above file if you notice line number 15.We have changed java package.For redeploying workflow definition there are 2 ways.<br />
First is changing <i>tomcat\webapps\alfresco\WEB-INF\classes\alfresco\bootstrap-context.xml</i> file and making redeploy true and than restart server.<br />
Second is do hot deployment of workflow.One of my colleague has written very good blog on <a href="https://techspreadwithshraddha.wordpress.com/category/java/alfresco/">Hot Deployment of Alfresco Workflow</a>.
<br />
<br />
<b>Step 2 : Change Site Invitation Java Custom Action</b><br />
<br />
First we will modify a file which is referenced in site invitation workflow.In that file we will set html parameter true.Below will be the content of that file.
<br />
<pre class="brush: java" name="code">/*
* Copyright (C) 2005-2010 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.invitation.site.ds;
import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.*;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.repo.i18n.MessageService;
import org.alfresco.repo.invitation.site.ds.InviteSender;
import org.alfresco.repo.jscript.ScriptNode;
import org.alfresco.repo.model.Repository;
import org.alfresco.repo.workflow.WorkflowModel;
import org.alfresco.repo.workflow.jbpm.JBPMSpringActionHandler;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.namespace.NamespaceService;
import org.jbpm.graph.exe.ExecutionContext;
import org.springframework.beans.factory.BeanFactory;
public class SendInviteAction extends JBPMSpringActionHandler
{
// TODO Select Version Id.
private static final long serialVersionUID = 8133039174866049136L;
private InviteSender inviteSender;
private NamespaceService namespaceService;
@Override
protected void initialiseHandler(BeanFactory factory)
{
Repository repository = (Repository) factory.getBean("repositoryHelper");
ServiceRegistry services = (ServiceRegistry) factory.getBean(ServiceRegistry.SERVICE_REGISTRY);
MessageService messageService= (MessageService) factory.getBean("messageService");
inviteSender = new InviteSender(services, repository, messageService);
namespaceService = services.getNamespaceService();
}
public void execute(final ExecutionContext context) throws Exception
{
Collection<String> propertyNames = Arrays.asList(wfVarInviteeUserName,//
wfVarResourceName,//
wfVarInviterUserName,//
wfVarInviteeUserName,//
wfVarRole,//
wfVarInviteeGenPassword,//
wfVarResourceName,//
wfVarInviteTicket,//
wfVarServerPath,//
wfVarAcceptUrl,//
wfVarRejectUrl,
InviteSender.WF_INSTANCE_ID);
Map<String, String> properties = makePropertiesFromContext(context, propertyNames);
String packageName = WorkflowModel.ASSOC_PACKAGE.toPrefixString(namespaceService).replace(":", "_");
ScriptNode packageNode = (ScriptNode) context.getVariable(packageName);
String packageRef = packageNode.getNodeRef().toString();
properties.put(InviteSender.WF_PACKAGE, packageRef);
String instanceName=WorkflowModel.PROP_WORKFLOW_INSTANCE_ID.toPrefixString(namespaceService).replace(":", "_");
String instanceId = (String) context.getVariable(instanceName);
properties.put(InviteSender.WF_INSTANCE_ID, instanceId);
properties.put(InviteSender.IS_HTML,"true");
inviteSender.sendMail(properties);
}
private Map<String, String> makePropertiesFromContext(ExecutionContext context, Collection<String> propertyNames)
{
Map<String, String> props = new HashMap<String, String>();
for (String name : propertyNames)
{
String value = (String) context.getVariable(name);
props.put(name, value);
}
return props;
}
}
</pre>
<br />
Now we will modify another file which is actually sending mail.In this we need to create our html action if the parameter html is true and we will set html parameter true if we want html content.Below is content of that file.Check line number 114 and 115 for this on below file.
<br />
<pre class="brush: java" name="code">/*
* Copyright (C) 2005-2010 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.invitation.site.ds;
import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.action.executer.MailActionExecuter;
import org.alfresco.repo.i18n.MessageService;
import org.alfresco.repo.model.Repository;
import org.alfresco.repo.search.SearcherException;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.action.ActionService;
import org.alfresco.service.cmr.invitation.InvitationException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.repository.TemplateService;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.cmr.site.SiteInfo;
import org.alfresco.service.cmr.site.SiteService;
import org.springframework.extensions.surf.util.ParameterCheck;
import org.springframework.extensions.surf.util.URLEncoder;
/**
* This class is responsible for sending email invitations, allowing nominated
* user's to join a Site.
*
* @author Nick Smith
*/
public class InviteSender
{
public static final String WF_INSTANCE_ID = "wf_instanceId";
public static final String WF_PACKAGE = "wf_package";
private static final List<String> expectedProperties = Arrays.asList(wfVarInviteeUserName,//
wfVarResourceName,//
wfVarInviterUserName,//
wfVarInviteeUserName,//
wfVarRole,//
wfVarInviteeGenPassword,//
wfVarResourceName,//
wfVarInviteTicket,//
wfVarServerPath,//
wfVarAcceptUrl,//
wfVarRejectUrl, WF_INSTANCE_ID,//
WF_PACKAGE);
public static final String IS_HTML="IS_HTML";
public static final String MAILHTMLACTION="mailHtmlAction";
private final ActionService actionService;
private final NodeService nodeService;
private final PersonService personService;
private final SearchService searchService;
private final SiteService siteService;
private final TemplateService templateService;
private final Repository repository;
private final MessageService messageService;
public InviteSender(ServiceRegistry services, Repository repository, MessageService messageService)
{
this.actionService = services.getActionService();
this.nodeService = services.getNodeService();
this.personService = services.getPersonService();
this.searchService = services.getSearchService();
this.siteService = services.getSiteService();
this.templateService = services.getTemplateService();
this.repository = repository;
this.messageService = messageService;
}
/**
* Sends an invitation email.
*
* @param properties A Map containing the properties needed to send the
* email.
*/
public void sendMail(Map<String, String> properties)
{
checkProperties(properties);
ParameterCheck.mandatory("Properties", properties);
NodeRef inviter = personService.getPerson(properties.get(wfVarInviterUserName));
String inviteeName = properties.get(wfVarInviteeUserName);
NodeRef invitee = personService.getPerson(inviteeName);
Action mail = null;
if(properties.get(InviteSender.IS_HTML).equals("true")){
mail=actionService.createAction(MAILHTMLACTION);
mail.setParameterValue("html",true);
}else{
mail=actionService.createAction(MailActionExecuter.NAME);
}
mail.setParameterValue(MailActionExecuter.PARAM_FROM, getEmail(inviter));
mail.setParameterValue(MailActionExecuter.PARAM_TO, getEmail(invitee));
mail.setParameterValue(MailActionExecuter.PARAM_SUBJECT, buildSubject(properties));
String mailText = buildMailText(properties, inviter, invitee);
mail.setParameterValue(MailActionExecuter.PARAM_TEXT, mailText);
actionService.executeAction(mail, getWorkflowPackage(properties));
}
/**
* @param properties
*/
private void checkProperties(Map<String, String> properties)
{
Set<String> keys = properties.keySet();
if (!keys.containsAll(expectedProperties))
{
LinkedList<String> missingProperties = new LinkedList<String>(expectedProperties);
missingProperties.removeAll(keys);
throw new InvitationException("The following mandatory properties are missing:\n" + missingProperties);
}
}
private String buildSubject(Map<String, String> properties)
{
return messageService.getMessage("invitation.invitesender.email.subject", getSiteName(properties));
}
private String buildMailText(Map<String, String> properties, NodeRef inviter, NodeRef invitee)
{
String template = getEmailTemplate();
Map<String, Object> model = makeDefaultModel();
Map<String, String> args = buildArgs(properties, inviter, invitee);
model.put("args", args);
return templateService.processTemplate(template, model);
}
private String getEmailTemplate()
{
NodeRef template = getEmailTemplateNodeRef();
return template.toString();
}
private Map<String, String> buildArgs(Map<String, String> properties, NodeRef inviter, NodeRef invitee)
{
String params = buildUrlParamString(properties);
String serverPath = properties.get(wfVarServerPath);
String acceptLink = serverPath + properties.get(wfVarAcceptUrl) + params;
String rejectLink = serverPath + properties.get(wfVarRejectUrl) + params;
Map<String, String> args = new HashMap<String, String>();
args.put("inviteePersonRef", invitee.toString());
args.put("inviterPersonRef", inviter.toString());
args.put("siteName", getSiteName(properties));
args.put("inviteeSiteRole", getRoleName(properties));
args.put("inviteeUserName", properties.get(wfVarInviteeUserName));
args.put("inviteeGenPassword", properties.get(wfVarInviteeGenPassword));
args.put("acceptLink", acceptLink);
args.put("rejectLink", rejectLink);
return args;
}
private String getRoleName(Map<String, String> properties) {
String roleName = properties.get(wfVarRole);
String role = messageService.getMessage("invitation.invitesender.email.role."+roleName);
if(role == null)
{
role = roleName;
}
return role;
}
private Map<String, Object> makeDefaultModel()
{
NodeRef person = repository.getPerson();
NodeRef companyHome = repository.getCompanyHome();
NodeRef userHome = repository.getUserHome(person);
Map<String, Object> model = templateService.buildDefaultModel(person, companyHome, userHome, null, null);
return model;
}
private String getEmail(NodeRef person)
{
return (String) nodeService.getProperty(person, ContentModel.PROP_EMAIL);
}
private NodeRef getWorkflowPackage(Map<String, String> properties)
{
String packageRef = properties.get(WF_PACKAGE);
return new NodeRef(packageRef);
}
private NodeRef getEmailTemplateNodeRef()
{
StoreRef spacesStore = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "SpacesStore");
String query = " PATH:\"app:company_home/app:dictionary/app:email_templates/cm:invite/cm:invite-email.ftl\"";
SearchParameters searchParams = new SearchParameters();
searchParams.addStore(spacesStore);
searchParams.setLanguage(SearchService.LANGUAGE_LUCENE);
searchParams.setQuery(query);
ResultSet results = null;
try
{
results = searchService.query(searchParams);
List<NodeRef> nodeRefs = results.getNodeRefs();
if (nodeRefs.size() == 1)
return nodeRefs.get(0);
else
throw new InvitationException("Cannot find the email templatte!");
}
catch (SearcherException e)
{
throw new InvitationException("Cannot find the email templatte!", e);
}
finally
{
if (results != null)
results.close();
}
}
private String buildUrlParamString(Map<String, String> properties)
{
StringBuilder params = new StringBuilder("?inviteId=");
params.append(properties.get(WF_INSTANCE_ID));
params.append("&inviteeUserName=");
params.append(URLEncoder.encode(properties.get(wfVarInviteeUserName)));
params.append("&siteShortName=");
params.append(properties.get(wfVarResourceName));
params.append("&inviteTicket=");
params.append(properties.get(wfVarInviteTicket));
return params.toString();
}
private String getSiteName(Map<String, String> properties)
{
String siteFullName = properties.get(wfVarResourceName);
SiteInfo site = siteService.getSite(siteFullName);
if (site == null)
throw new InvitationException("The site " + siteFullName + " could not be found.");
String siteName = site.getShortName();
String siteTitle = site.getTitle();
if (siteTitle != null && siteTitle.length() > 0)
{
siteName = siteTitle;
}
return siteName;
}
}
</pre>
<br />
<br />
<b>Step 3 :Add html content in site invitation template</b><br />
Now modify the content of site invitation template, as we are doing normally.
<br />
<div>
</div>
</div>
<div class="blogger-post-footer">https://scontent-b-mxp.xx.fbcdn.net/hphotos-xap1/v/t1.0-9/10675541_896261013719814_5601513019470361090_n.jpg?oh=741b05a81becaae8bce36db141948a4a&oe=5531762A</div>Krutik Jayswalhttp://www.blogger.com/profile/16691396948811505379noreply@blogger.comtag:blogger.com,1999:blog-2571457445842624811.post-9101151932459575892015-07-13T02:42:00.000-07:002016-08-26T13:06:07.536-07:00HTML Mail Action in alfresco(3.4d)<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
Just a few days before I was having requirement for sending notification mail which contains HTML text in alfresco.Alfresco version in which i have to do this was 3.4d.Sending mail in alfresco is not much difficult, as there are many things all ready created for us for example custom java action for sending mail.<br />
We only need to add parameters like mail text , subject ,receiver etc...We can simply achieve this by below code.
<br />
<br />
<pre class="javascript" name="code">var mail = actions.create("mail");
mail.parameters.to = "krutik.jayswal@gmail.com";
mail.parameters.subject = "Html test";
mail.parameters.from = "alfresco.architect@mail.com";
mail.parameters.text = "My name is Krutik Jayswal<b> if you see this it is very bold</b>";
mail.parameters.node=document;
mail.execute(document);
</pre>
<br />
But above was not working in version below alfresco 3.4d.Alfresco version <=3.4d does not supports html mail content.So for this we need to create one custom action which supports html mail text.For that you need to follow below steps.
</div>
</div>
<br />
<br />
<b>Step 1 : Create Custom Html Action</b><br />
Below is Java class for that.Save it as HTMLMailFormatter.java.I did little customization in the in built mail action.
<br />
<pre class="java" name="code">/*
* Copyright (C) 2005-2010 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package com.mail;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.action.ParameterDefinitionImpl;
import org.alfresco.repo.action.executer.ActionExecuterAbstractBase;
import org.alfresco.repo.action.executer.TestModeable;
import org.alfresco.repo.template.DateCompareMethod;
import org.alfresco.repo.template.HasAspectMethod;
import org.alfresco.repo.template.I18NMessageMethod;
import org.alfresco.repo.template.TemplateNode;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.action.ParameterDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.TemplateService;
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.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.validator.EmailValidator;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.mail.MailException;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.mail.javamail.MimeMessagePreparator;
/**
* Mail action executor implementation.
*
* @author Roy Wetherall
*/
public class HTMLMailFormatter extends ActionExecuterAbstractBase
implements InitializingBean, TestModeable
{
private static Log logger = LogFactory.getLog(HTMLMailFormatter.class);
/**
* Action executor constants
*/
public static final String NAME = "mail";
public static final String PARAM_TO = "to";
public static final String PARAM_TO_MANY = "to_many";
public static final String PARAM_SUBJECT = "subject";
public static final String PARAM_TEXT = "text";
public static final String PARAM_FROM = "from";
public static final String PARAM_TEMPLATE = "template";
public static final String IS_HTML_SUPPORTED= "html";
/**
* From address
*/
private static final String FROM_ADDRESS = "alfresco@alfresco.org";
private static final String REPO_REMOTE_URL = "http://localhost:8080/alfresco";
/**
* The java mail sender
*/
private JavaMailSender javaMailSender;
/**
* The Template service
*/
private TemplateService templateService;
/**
* The Person service
*/
private PersonService personService;
/**
* The Authentication service
*/
private AuthenticationService authService;
/**
* The Node Service
*/
private NodeService nodeService;
/**
* The Authority Service
*/
private AuthorityService authorityService;
/**
* The Service registry
*/
private ServiceRegistry serviceRegistry;
/**
* Mail header encoding scheme
*/
private String headerEncoding = null;
/**
* Default from address
*/
private String fromAddress = null;
/**
* Default alfresco installation url
*/
private String repoRemoteUrl = null;
private boolean sendTestMessage = false;
private String testMessageTo = null;
private String testMessageSubject = "Test message";
private String testMessageText = "This is a test message.";
/**
* Test mode prevents email messages from being sent.
* It is used when unit testing when we don't actually want to send out email messages.
*
* MER 20/11/2009 This is a quick and dirty fix. It should be replaced by being
* "mocked out" or some other better way of running the unit tests.
*/
private boolean testMode = false;
private MimeMessage lastTestMessage;
/**
* @param javaMailSender the java mail sender
*/
public void setMailService(JavaMailSender javaMailSender)
{
this.javaMailSender = javaMailSender;
}
/**
* @param templateService the TemplateService
*/
public void setTemplateService(TemplateService templateService)
{
this.templateService = templateService;
}
/**
* @param personService the PersonService
*/
public void setPersonService(PersonService personService)
{
this.personService = personService;
}
/**
* @param authService the AuthenticationService
*/
public void setAuthenticationService(AuthenticationService authService)
{
this.authService = authService;
}
/**
* @param serviceRegistry the ServiceRegistry
*/
public void setServiceRegistry(ServiceRegistry serviceRegistry)
{
this.serviceRegistry = serviceRegistry;
}
/**
* @param authorityService the AuthorityService
*/
public void setAuthorityService(AuthorityService authorityService)
{
this.authorityService = authorityService;
}
/**
* @param nodeService the NodeService to set.
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
/**
* @param headerEncoding The mail header encoding to set.
*/
public void setHeaderEncoding(String headerEncoding)
{
this.headerEncoding = /*
* Copyright (C) 2005-2010 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.invitation.site.ds;
import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.action.executer.MailActionExecuter;
import org.alfresco.repo.i18n.MessageService;
import org.alfresco.repo.model.Repository;
import org.alfresco.repo.search.SearcherException;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.action.ActionService;
import org.alfresco.service.cmr.invitation.InvitationException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.repository.TemplateService;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.cmr.site.SiteInfo;
import org.alfresco.service.cmr.site.SiteService;
import org.springframework.extensions.surf.util.ParameterCheck;
import org.springframework.extensions.surf.util.URLEncoder;
/**
* This class is responsible for sending email invitations, allowing nominated
* user's to join a Site.
*
* @author Nick Smith
*/
public class InviteSender
{
public static final String WF_INSTANCE_ID = "wf_instanceId";
public static final String WF_PACKAGE = "wf_package";
private static final List<String> expectedProperties = Arrays.asList(wfVarInviteeUserName,//
wfVarResourceName,//
wfVarInviterUserName,//
wfVarInviteeUserName,//
wfVarRole,//
wfVarInviteeGenPassword,//
wfVarResourceName,//
wfVarInviteTicket,//
wfVarServerPath,//
wfVarAcceptUrl,//
wfVarRejectUrl, WF_INSTANCE_ID,//
WF_PACKAGE);
public static final String IS_HTML="IS_HTML";
public static final String MAILHTMLACTION="mailHtmlAction";
private final ActionService actionService;
private final NodeService nodeService;
private final PersonService personService;
private final SearchService searchService;
private final SiteService siteService;
private final TemplateService templateService;
private final Repository repository;
private final MessageService messageService;
public InviteSender(ServiceRegistry services, Repository repository, MessageService messageService)
{
this.actionService = services.getActionService();
this.nodeService = services.getNodeService();
this.personService = services.getPersonService();
this.searchService = services.getSearchService();
this.siteService = services.getSiteService();
this.templateService = services.getTemplateService();
this.repository = repository;
this.messageService = messageService;
}
/**
* Sends an invitation email.
*
* @param properties A Map containing the properties needed to send the
* email.
*/
public void sendMail(Map<String, String> properties)
{
checkProperties(properties);
ParameterCheck.mandatory("Properties", properties);
NodeRef inviter = personService.getPerson(properties.get(wfVarInviterUserName));
String inviteeName = properties.get(wfVarInviteeUserName);
NodeRef invitee = personService.getPerson(inviteeName);
Action mail = null;
if(properties.get(InviteSender.IS_HTML).equals("true")){
mail=actionService.createAction(MAILHTMLACTION);
mail.setParameterValue("html",true);
}else{
mail=actionService.createAction(MailActionExecuter.NAME);
}
mail.setParameterValue(MailActionExecuter.PARAM_FROM, getEmail(inviter));
mail.setParameterValue(MailActionExecuter.PARAM_TO, getEmail(invitee));
mail.setParameterValue(MailActionExecuter.PARAM_SUBJECT, buildSubject(properties));
String mailText = buildMailText(properties, inviter, invitee);
mail.setParameterValue(MailActionExecuter.PARAM_TEXT, mailText);
actionService.executeAction(mail, getWorkflowPackage(properties));
}
/**
* @param properties
*/
private void checkProperties(Map<String, String> properties)
{
Set<String> keys = properties.keySet();
if (!keys.containsAll(expectedProperties))
{
LinkedList<String> missingProperties = new LinkedList<String>(expectedProperties);
missingProperties.removeAll(keys);
throw new InvitationException("The following mandatory properties are missing:\n" + missingProperties);
}
}
private String buildSubject(Map<String, String> properties)
{
return messageService.getMessage("invitation.invitesender.email.subject", getSiteName(properties));
}
private String buildMailText(Map<String, String> properties, NodeRef inviter, NodeRef invitee)
{
String template = getEmailTemplate();
Map<String, Object> model = makeDefaultModel();
Map<String, String> args = buildArgs(properties, inviter, invitee);
model.put("args", args);
return templateService.processTemplate(template, model);
}
private String getEmailTemplate()
{
NodeRef template = getEmailTemplateNodeRef();
return template.toString();
}
private Map<String, String> buildArgs(Map<String, String> properties, NodeRef inviter, NodeRef invitee)
{
String params = buildUrlParamString(properties);
String serverPath = properties.get(wfVarServerPath);
String acceptLink = serverPath + properties.get(wfVarAcceptUrl) + params;
String rejectLink = serverPath + properties.get(wfVarRejectUrl) + params;
Map<String, String> args = new HashMap<String, String>();
args.put("inviteePersonRef", invitee.toString());
args.put("inviterPersonRef", inviter.toString());
args.put("siteName", getSiteName(properties));
args.put("inviteeSiteRole", getRoleName(properties));
args.put("inviteeUserName", properties.get(wfVarInviteeUserName));
args.put("inviteeGenPassword", properties.get(wfVarInviteeGenPassword));
args.put("acceptLink", acceptLink);
args.put("rejectLink", rejectLink);
return args;
}
private String getRoleName(Map<String, String> properties) {
String roleName = properties.get(wfVarRole);
String role = messageService.getMessage("invitation.invitesender.email.role."+roleName);
if(role == null)
{
role = roleName;
}
return role;
}
private Map<String, Object> makeDefaultModel()
{
NodeRef person = repository.getPerson();
NodeRef companyHome = repository.getCompanyHome();
NodeRef userHome = repository.getUserHome(person);
Map<String, Object> model = templateService.buildDefaultModel(person, companyHome, userHome, null, null);
return model;
}
private String getEmail(NodeRef person)
{
return (String) nodeService.getProperty(person, ContentModel.PROP_EMAIL);
}
private NodeRef getWorkflowPackage(Map<String, String> properties)
{
String packageRef = properties.get(WF_PACKAGE);
return new NodeRef(packageRef);
}
private NodeRef getEmailTemplateNodeRef()
{
StoreRef spacesStore = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "SpacesStore");
String query = " PATH:\"app:company_home/app:dictionary/app:email_templates/cm:invite/cm:invite-email.ftl\"";
SearchParameters searchParams = new SearchParameters();
searchParams.addStore(spacesStore);
searchParams.setLanguage(SearchService.LANGUAGE_LUCENE);
searchParams.setQuery(query);
ResultSet results = null;
try
{
results = searchService.query(searchParams);
List<NodeRef> nodeRefs = results.getNodeRefs();
if (nodeRefs.size() == 1)
return nodeRefs.get(0);
else
throw new InvitationException("Cannot find the email templatte!");
}
catch (SearcherException e)
{
throw new InvitationException("Cannot find the email templatte!", e);
}
finally
{
if (results != null)
results.close();
}
}
private String buildUrlParamString(Map<String, String> properties)
{
StringBuilder params = new StringBuilder("?inviteId=");
params.append(properties.get(WF_INSTANCE_ID));
params.append("&inviteeUserName=");
params.append(URLEncoder.encode(properties.get(wfVarInviteeUserName)));
params.append("&siteShortName=");
params.append(properties.get(wfVarResourceName));
params.append("&inviteTicket=");
params.append(properties.get(wfVarInviteTicket));
return params.toString();
}
private String getSiteName(Map<String, String> properties)
{
String siteFullName = properties.get(wfVarResourceName);
SiteInfo site = siteService.getSite(siteFullName);
if (site == null)
throw new InvitationException("The site " + siteFullName + " could not be found.");
String siteName = site.getShortName();
String siteTitle = site.getTitle();
if (siteTitle != null && siteTitle.length() > 0)
{
siteName = siteTitle;
}
return siteName;
}
}gistry, null));
// current date/time is useful to have and isn't supplied by FreeMarker by default
model.put("date", new Date());
// add custom method objects
model.put("hasAspect", new HasAspectMethod());
model.put("message", new I18NMessageMethod());
model.put("dateCompare", new DateCompareMethod());
model.put("url", new URLHelper(repoRemoteUrl));
return model;
}
/**
* Add the parameter definitions
*/
@Override
protected void addParameterDefinitions(List<ParameterDefinition> paramList)
{
paramList.add(new ParameterDefinitionImpl(PARAM_TO, DataTypeDefinition.TEXT, false, getParamDisplayLabel(PARAM_TO)));
paramList.add(new ParameterDefinitionImpl(PARAM_TO_MANY, DataTypeDefinition.ANY, false, getParamDisplayLabel(PARAM_TO_MANY), true));
paramList.add(new ParameterDefinitionImpl(PARAM_SUBJECT, DataTypeDefinition.TEXT, true, getParamDisplayLabel(PARAM_SUBJECT)));
paramList.add(new ParameterDefinitionImpl(PARAM_TEXT, DataTypeDefinition.TEXT, false, getParamDisplayLabel(PARAM_TEXT)));
paramList.add(new ParameterDefinitionImpl(PARAM_FROM, DataTypeDefinition.TEXT, false, getParamDisplayLabel(PARAM_FROM)));
paramList.add(new ParameterDefinitionImpl(PARAM_TEMPLATE, DataTypeDefinition.NODE_REF, false, getParamDisplayLabel(PARAM_TEMPLATE), false, "ac-email-templates"));
}
public void setTestMode(boolean testMode)
{
this.testMode = testMode;
}
public boolean isTestMode()
{
return testMode;
}
/**
* Returns the most recent message that wasn't sent
* because TestMode had been enabled.
*/
public MimeMessage retrieveLastTestMessage()
{
return lastTestMessage;
}
public static class URLHelper
{
String contextPath;
String serverPath;
public URLHelper(String repoRemoteUrl)
{
String[] parts = repoRemoteUrl.split("/");
this.contextPath = "/" + parts[parts.length - 1];
this.serverPath = parts[0] + "//" + parts[2];
}
public String getContext()
{
return this.contextPath;
}
public String getServerPath()
{
return this.serverPath;
}
}
}
</pre>
</div>
Below is context file for the same.Put it inside <i>tomcat/shared/classes/alfresco/extension/mail-context.xml</i>.
<br />
<br />
<pre class="xml" name="code">
<beans>
<bean class="com.mail.HTMLMailFormatter" id="mailHtmlAction" parent="action-executer">
<property name="mailService">
<ref bean="mailService"></ref>
</property>
<property name="templateService">
<ref bean="templateService"></ref>
</property>
<property name="personService">
<ref bean="personService"></ref>
</property>
<property name="authenticationService">
<ref bean="authenticationService"></ref>
</property>
<property name="nodeService">
<ref bean="nodeService"></ref>
</property>
<property name="authorityService">
<ref bean="authorityService"></ref>
</property>
<property name="serviceRegistry">
<ref bean="ServiceRegistry"></ref>
</property>
<property name="headerEncoding">
<value>${mail.header}</value>
</property>
<property name="fromAddress">
<value>${mail.from.default}</value>
</property>
<property name="repoRemoteUrl">
<value>${repo.remote.url}</value>
</property>
<property name="testMessageTo">
<value>${mail.testmessage.to}</value>
</property>
<property name="testMessageSubject">
<value>${mail.testmessage.subject}</value>
</property>
<property name="testMessageText">
<value>${mail.testmessage.text}</value>
</property>
</bean>
</beans>
</pre>
<b>Step 2 : Create Code for Executing Custom Action</b><br />
We can execute Custom action from anywhere in alfresco ,whether it is workflow , javascript , webscript or inside any other custom action.We will use javascript for executing this code.
<br />
<br />
<pre class="javascript" name="code">var mail = actions.create("mail");
mail.parameters.to = "krutik.jayswal@gmail.com";
mail.parameters.subject = "Html test";
mail.parameters.html = "true"; //For setting content as html.
mail.parameters.from = "alfresco.architect@mail.com";
mail.parameters.text = "My name is Krutik Jayswal<b> if you see this it is very bold</b>";
mail.parameters.node=document;
mail.execute(document);
</pre>
I hope you have noticed line number 4 in above code.That is used for setting html content.
Hope this helps.</div>
<div class="blogger-post-footer">https://scontent-b-mxp.xx.fbcdn.net/hphotos-xap1/v/t1.0-9/10675541_896261013719814_5601513019470361090_n.jpg?oh=741b05a81becaae8bce36db141948a4a&oe=5531762A</div>Krutik Jayswalhttp://www.blogger.com/profile/16691396948811505379noreply@blogger.comtag:blogger.com,1999:blog-2571457445842624811.post-18886214154110274772014-12-09T04:38:00.000-08:002014-12-09T04:38:34.699-08:00Configuring CIFS(Common Internet File System) with alfresco<div dir="ltr" style="text-align: left;" trbidi="on">
After struggling a lot I found that Its very easy to configure CIFS with alfresco in Windows Server.<br />
<br />
<br />
You only need to follow some basic steps which are available in many please(Steps are at end).But this is not only for the step which you will need to follow for CIFS configuration,you should also know how to debug if your configuration is not proper or something is missing and you dont know what is missing.Please refere below things for same.<br />
<br />
<b>netstat -a</b><br />
<br />
This command is manly used for finding out which port is occupied.If you want port with process id you can use below command<br />
<br />
<b>netstat -a -o -n</b><br />
<b><br /></b>
<b><br /></b>
Both of above commands can be used for identifying that the port 445 is used or not.<br />
<br />
<b>net view ServerName</b><br />
<br />
above command is identification for server access.It will give you error code so that troubleshott becomes easy.<br />
<br />
<span style="background-color: #fafafa; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 21px;"><b>nbtstat -a SERVER</b></span><br />
<span style="background-color: #fafafa; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 21px;"><b><br /></b></span>
<span style="background-color: #fafafa; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 21px;">Testing cifs server name</span><br />
<br />
<br />
<br />
Below are steps for alfresco CIFS configuration.Which is taken from docs.alfresco.com.<br />
<br />
<ol class="ol steps" style="background-color: white; box-sizing: border-box; color: #58595b; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4444446563721px; line-height: 22.2222232818604px; margin: 20px 0px;">
<li class="li step" style="box-sizing: border-box; margin-bottom: 5px;"><span class="ph cmd" style="box-sizing: border-box;">Install Windows Server 2008 R2 out-of-the box. </span>You do not need to change the <span class="ph filepath" style="box-sizing: border-box; font-family: 'Courier New', Courier, monospace;">/etc/hosts</span> or File and Printer Sharing configuration. </li>
<li class="li step" style="box-sizing: border-box; margin-bottom: 5px;"><span class="ph cmd" style="box-sizing: border-box;">Configure a WINS server.</span><ol class="ol substeps" id="fileserv-CIFS-WS2008R2__substeps_kgh_iyf_xf" style="box-sizing: border-box; margin: 0px;" type="a">
<li class="li substep" style="box-sizing: border-box; margin-bottom: 5px;"><span class="ph cmd" style="box-sizing: border-box;">If the server is a domain controller or already part of a domain, this may already be controlled by a Domain Policy. </span>To install one on Windows Server 2008 R2, see the following article: <a class="xref" href="http://technet.microsoft.com/en-us/library/ff710463%28WS.10%29.aspx" style="box-sizing: border-box; color: #56a3d9; font-weight: bold; text-decoration: none;" target="_blank">http://technet.microsoft.com/en-us/library/ff710463%28WS.10%29.aspx</a>.</li>
<li class="li substep" style="box-sizing: border-box; margin-bottom: 5px;"><span class="ph cmd" style="box-sizing: border-box;">To manually configure an existing WINS server use the following steps: </span><ol class="ol" id="fileserv-CIFS-WS2008R2__ol_dpz_gzf_xf" style="box-sizing: border-box; margin: 0px;" type="i">
<li class="li" style="box-sizing: border-box; margin-bottom: 5px;">Go to <span class="ph uicontrol" style="box-sizing: border-box; font-weight: bold;">Control Panel\Network and Internet\Network and Sharing Center > Change Adapter Settings > Local Area Connection > Properties</span>.</li>
<li class="li" style="box-sizing: border-box; margin-bottom: 5px;">Select <span class="ph uicontrol" style="box-sizing: border-box; font-weight: bold;">Internet Protocol Version 4 (TCP/IPv4)</span> and then select <span class="ph uicontrol" style="box-sizing: border-box; font-weight: bold;">Properties</span>. .</li>
<li class="li" style="box-sizing: border-box; margin-bottom: 5px;">On the <span class="ph uicontrol" style="box-sizing: border-box; font-weight: bold;">General</span> tab, select <span class="ph uicontrol" style="box-sizing: border-box; font-weight: bold;">Advanced</span> and then select the <span class="ph uicontrol" style="box-sizing: border-box; font-weight: bold;">WINS</span> tab.</li>
<li class="li" style="box-sizing: border-box; margin-bottom: 5px;">Click <span class="ph uicontrol" style="box-sizing: border-box; font-weight: bold;">Add</span> and then add the IP address of the WINS server in your network and select <span class="ph uicontrol" style="box-sizing: border-box; font-weight: bold;">Enable NetBIOS over TCP/IP</span>.</li>
<li class="li" style="box-sizing: border-box; margin-bottom: 5px;">Click <span class="ph uicontrol" style="box-sizing: border-box; font-weight: bold;">OK > OK > Close</span>.</li>
</ol>
</li>
</ol>
</li>
<li class="li step" style="box-sizing: border-box; margin-bottom: 5px;"><span class="ph cmd" style="box-sizing: border-box;">Ensure that you install Alfresco using the x64 setup wizard. </span>See <a class="xref" href="http://docs.alfresco.com/4.1/tasks/simpleinstall-enterprise-win.html" style="box-sizing: border-box; color: #56a3d9; font-weight: bold; text-decoration: none;" title="The setup wizard for Microsoft Windows installs all the software and components that you require for running Alfresco. This setup wizard installs Alfresco and additional software, including a Tomcat application server, PostgreSQL database, JDK, OpenOffice, SWFTools, and ImageMagick.">Installing Alfresco Enterprise on Windows</a>.</li>
<li class="li step" style="box-sizing: border-box; margin-bottom: 5px;"><span class="ph cmd" style="box-sizing: border-box;">Configure the Windows Server 2008 R2 firewall to create a rule to block 445.</span><ol class="ol substeps" id="fileserv-CIFS-WS2008R2__substeps_dcg_oqb_xf" style="box-sizing: border-box; margin: 0px;" type="a">
<li class="li substep" style="box-sizing: border-box; margin-bottom: 5px;"><span class="ph cmd" style="box-sizing: border-box;">Open <span class="ph uicontrol" style="box-sizing: border-box; font-weight: bold;">Control Panel\Network and Internet\Network and Sharing Center > Windows Firewall > Advanced Settings</span>.</span></li>
<li class="li substep" style="box-sizing: border-box; margin-bottom: 5px;"><span class="ph cmd" style="box-sizing: border-box;">Select <span class="ph uicontrol" style="box-sizing: border-box; font-weight: bold;">Inbound Rules</span>.</span></li>
<li class="li substep" style="box-sizing: border-box; margin-bottom: 5px;"><span class="ph cmd" style="box-sizing: border-box;">On the right-side of the window, click <span class="ph uicontrol" style="box-sizing: border-box; font-weight: bold;">New Rule</span>.</span></li>
<li class="li substep" style="box-sizing: border-box; margin-bottom: 5px;"><span class="ph cmd" style="box-sizing: border-box;">Follow the instructions on the wizard:</span><ol class="ol" style="box-sizing: border-box; margin: 0px;" type="i">
<li class="li" style="box-sizing: border-box; margin-bottom: 5px;">Rule Type > Port, Next.</li>
<li class="li" style="box-sizing: border-box; margin-bottom: 5px;">Rule apply to "TCP", Specific Local Ports > 445, Next,</li>
<li class="li" style="box-sizing: border-box; margin-bottom: 5px;">Action > Block the connection, Next,</li>
<li class="li" style="box-sizing: border-box; margin-bottom: 5px;">Profile > Select ALL network types (Domain, Public, Private)</li>
<li class="li" style="box-sizing: border-box; margin-bottom: 5px;">Name > "Alfresco CIFS (Block 445)", Description the same.</li>
</ol>
</li>
<li class="li substep" style="box-sizing: border-box; margin-bottom: 5px;"><span class="ph cmd" style="box-sizing: border-box;">Select <span class="ph uicontrol" style="box-sizing: border-box; font-weight: bold;">Finish</span>.</span></li>
</ol>
</li>
<li class="li step" style="box-sizing: border-box; margin-bottom: 5px;"><span class="ph cmd" style="box-sizing: border-box;">Configure the Windows Server 2008 R2 firewall to create a rule to allow 137,138,139.</span><ol class="ol substeps" id="fileserv-CIFS-WS2008R2__substeps_iog_fxf_xf" style="box-sizing: border-box; margin: 0px;" type="a">
<li class="li substep" style="box-sizing: border-box; margin-bottom: 5px;"><span class="ph cmd" style="box-sizing: border-box;">Open the <span class="ph uicontrol" style="box-sizing: border-box; font-weight: bold;">Control Panel\Network and Internet\Network and Sharing Center > Windows Firewall > Advanced Settings</span>.</span></li>
<li class="li substep" style="box-sizing: border-box; margin-bottom: 5px;"><span class="ph cmd" style="box-sizing: border-box;">Select <span class="ph uicontrol" style="box-sizing: border-box; font-weight: bold;">Inbound Rules</span>.</span></li>
<li class="li substep" style="box-sizing: border-box; margin-bottom: 5px;"><span class="ph cmd" style="box-sizing: border-box;">On the right-side of the window, click <span class="ph uicontrol" style="box-sizing: border-box; font-weight: bold;">New Rule</span>.</span></li>
<li class="li substep" style="box-sizing: border-box; margin-bottom: 5px;"><span class="ph cmd" style="box-sizing: border-box;">Follow the instructions on the wizard:</span><ol class="ol" id="fileserv-CIFS-WS2008R2__ol_vtx_vzn_xf" style="box-sizing: border-box; margin: 0px;" type="i">
<li class="li" style="box-sizing: border-box; margin-bottom: 5px;">Rule Type > Port, Next.</li>
<li class="li" style="box-sizing: border-box; margin-bottom: 5px;">Rule apply to "TCP", Specific Local Ports > 137,138,139, Next,</li>
<li class="li" style="box-sizing: border-box; margin-bottom: 5px;">Action > Allow the connection, Next,</li>
<li class="li" style="box-sizing: border-box; margin-bottom: 5px;">Profile > Select ALL network types (Domain, Public, Private)</li>
<li class="li" style="box-sizing: border-box; margin-bottom: 5px;">Name > "Alfresco CIFS (Allow 137,138,139)", Description the same.</li>
</ol>
</li>
<li class="li substep" style="box-sizing: border-box; margin-bottom: 5px;"><span class="ph cmd" style="box-sizing: border-box;">Select <span class="ph uicontrol" style="box-sizing: border-box; font-weight: bold;">Finish</span>.</span></li>
</ol>
</li>
<li class="li step" style="box-sizing: border-box; margin-bottom: 5px;"><span class="ph cmd" style="box-sizing: border-box;">Configure the client (Windows XP and Windows 7)</span><ol class="ol substeps" id="fileserv-CIFS-WS2008R2__substeps_kcq_ayf_xf" style="box-sizing: border-box; margin: 0px;" type="a">
<li class="li substep" style="box-sizing: border-box; margin-bottom: 5px;"><span class="ph cmd" style="box-sizing: border-box;">Go to <span class="ph uicontrol" style="box-sizing: border-box; font-weight: bold;">Control Panel\Network and Internet\Network and Sharing Center > Change Adapter Settings > Local Area Connection > Properties</span>. </span></li>
<li class="li substep" style="box-sizing: border-box; margin-bottom: 5px;"><span class="ph cmd" style="box-sizing: border-box;">Select <span class="ph uicontrol" style="box-sizing: border-box; font-weight: bold;">Internet Protocol Version 4 (TCP/IPv4)</span> and click <span class="ph uicontrol" style="box-sizing: border-box; font-weight: bold;">Properties</span>.</span></li>
<li class="li substep" style="box-sizing: border-box; margin-bottom: 5px;"><span class="ph cmd" style="box-sizing: border-box;">On the <span class="ph uicontrol" style="box-sizing: border-box; font-weight: bold;">General</span> tab, select <span class="ph uicontrol" style="box-sizing: border-box; font-weight: bold;">Advanced</span> and then select the <span class="ph uicontrol" style="box-sizing: border-box; font-weight: bold;">WINS</span> tab.</span></li>
<li class="li substep" style="box-sizing: border-box; margin-bottom: 5px;"><span class="ph cmd" style="box-sizing: border-box;">Click <span class="ph uicontrol" style="box-sizing: border-box; font-weight: bold;">Add</span> and then add the IP address of the WINS server in your network and select <span class="ph uicontrol" style="box-sizing: border-box; font-weight: bold;">Enable NetBIOS over TCP/IP</span>.</span></li>
<li class="li substep" style="box-sizing: border-box; margin-bottom: 5px;"><span class="ph cmd" style="box-sizing: border-box;">Click <span class="ph uicontrol" style="box-sizing: border-box; font-weight: bold;">OK > OK > Close</span>. </span></li>
</ol>
</li>
</ol>
<br />
<br /></div>
<div class="blogger-post-footer">https://scontent-b-mxp.xx.fbcdn.net/hphotos-xap1/v/t1.0-9/10675541_896261013719814_5601513019470361090_n.jpg?oh=741b05a81becaae8bce36db141948a4a&oe=5531762A</div>Krutik Jayswalhttp://www.blogger.com/profile/16691396948811505379noreply@blogger.com0tag:blogger.com,1999:blog-2571457445842624811.post-36493015027561997402014-04-09T22:13:00.003-07:002014-04-09T22:13:36.066-07:00Alfresco Installation Steps<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="MsoNormal">
<h1>
Alfresco Installation Steps (alfresco 4.2d)</h1>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
If not already done, install the jdk on your machine.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
a. Set the standard Environment Variables (JAVA_HOME, etc).</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
b. Set the non-standard Environment Variables (JAVA_OPTS).</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Install OpenOffice.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
1. Download alfresco and tomcat 7.0.42 or above.</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
2. Create Folder Named “Alfresco “</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
3. Put Tomcat inside Alfresco Folder.</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
4. Copy content of “alfresco-community-4.2c/bin” to “tomcat/bin”.</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
5. Copy “alfresco-community-4.2c/web-server/shared” & </div>
<div class="MsoNormal">
“alfresco-community-4.2c/web-sserver/endorsed” folder into “tomcat ”</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
6. Copy files “alfresco.war “and “share.war” from “alfresco-community-4.2c/web-server/webapps” folder to “tomcat/webapps/”</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
7. Copy “mysql.jar”(your dbms driver file) inside “tomcat/lib”.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
8. Open “Alfresco\Tomcat\shared\classes\ alfresco-global.properties” in notepad++.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
9. Create database inside mysql,give that db name in alfresco-global.properties ;</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
10. Uncomment from below line and set appropriate property to them</div>
<div class="MsoNormal">
<br />
db.username=root //username of dbms user</div>
<div class="MsoNormal">
db.password=root // password of dbms user</div>
<div class="MsoNormal">
dir.root=D:/Alfresco/alf_data</div>
<div class="MsoNormal">
db.driver=org.gjt.mm.mysql.Driver</div>
<div class="MsoNormal">
db.url=jdbc:mysql://localhost/DBNAME?useUnicode=yes&characterEncoding=UTF-8</div>
<div class="MsoNormal">
Here DBNAME is your mysql database name.<br />
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
11. Open the “tomcat/conf/catalina.properties” file.</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
12. Change the value of the shared.loader= property to the following </div>
<div class="MsoNormal">
shared.loader=${catalina.base}/shared/classes,</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
13. Open the "D:\Alfresco\Tomcat\bin\catalina.bat" file.</div>
<div class="MsoNormal">
append below line in “JAVA_OPTS” variable(it may be on line number 182)<br />
<br /></div>
<div class="MsoNormal">
-Xms512M -Xmx512M -XX:MaxPermSize=512M</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<br />
<div class="MsoNormal">
</div>
<br />
<div class="MsoNormal" style="-webkit-text-stroke-width: 0px; color: black; font-family: 'Times New Roman'; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
<div style="margin: 0px;">
<br /></div>
</div>
</div>
<div class="blogger-post-footer">https://scontent-b-mxp.xx.fbcdn.net/hphotos-xap1/v/t1.0-9/10675541_896261013719814_5601513019470361090_n.jpg?oh=741b05a81becaae8bce36db141948a4a&oe=5531762A</div>Krutik Jayswalhttp://www.blogger.com/profile/16691396948811505379noreply@blogger.com1tag:blogger.com,1999:blog-2571457445842624811.post-1773374080113176432014-03-28T11:47:00.001-07:002014-03-28T11:47:43.552-07:00Alfresco Replication Jobs<div dir="ltr" style="text-align: left;" trbidi="on">
<h1 class="title topictitle1" style="background-color: white; margin-bottom: 0.6em; margin-top: 0pc;">
<div class="shortdesc" style="color: #333333; font-family: Helvetica; font-size: 15px; font-weight: normal;">
Replication jobs is a feature that allows you to control the replication of content between different Alfresco repositories.</div>
<div class="p" style="color: #333333; font-family: Helvetica; font-size: 15px; font-weight: normal; margin-top: 1em;">
You manage replication jobs using the Admin Console tool in Alfresco Share, which provides the user interface for the replication service.</div>
<div class="p" style="color: #333333; font-family: Helvetica; font-size: 15px; font-weight: normal; margin-top: 1em;">
The replication service is responsible for persisting replication jobs that specify what is to be replicated, to where, and when. In addition, it monitors the status of currently executing replication jobs and allows you to cancel replications. The replication service finds the nodes that need to be transferred, and then it delegates to the transfer service.</div>
<div class="p" style="color: #333333; font-family: Helvetica; font-size: 15px; font-weight: normal; margin-top: 1em;">
Before you can use the replication jobs feature, you must set up transfer target definitions to specify where the transfer should be sent.</div>
</h1>
<h1 class="title topictitle1" style="background-color: white; color: #00ae42; font-family: Helvetica; font-size: 18pt; font-weight: normal; margin-bottom: 0.6em; margin-top: 0pc;">
<span style="font-size: 18pt;"><br /></span></h1>
<h1 class="title topictitle1" style="background-color: white; color: #00ae42; font-family: Helvetica; font-size: 18pt; font-weight: normal; margin-bottom: 0.6em; margin-top: 0pc;">
<span style="font-size: 18pt;">Transfer target for replication jobs</span></h1>
<div class="body taskbody" style="color: #333333; font-family: Helvetica; font-size: 15px;">
<div class="shortdesc">
To use the replication jobs feature for replicating content across Alfresco repositories, you need to create a transfer target definition (in the source Alfresco server) to specify where the transfer should go.</div>
<div class="section context" style="margin-bottom: 1em; margin-top: 1em;">
The files that control and monitor the transfer service are stored using a folder in <span class="ph">Alfresco</span> Share, in the <span class="ph uicontrol" style="font-weight: bold;">Transfers</span> space under<span class="ph uicontrol" style="font-weight: bold;">Data Dictionary</span>. The <span class="ph uicontrol" style="font-weight: bold;">Transfer Target Groups</span> space contains the transfer target definitions that specify the destination of the transfer. The group level below this space, called <span class="ph uicontrol" style="font-weight: bold;">Default Group</span>, is used to classify different sets of transfer targets.</div>
<span class="ph cmd">On the source Alfresco server, browse to <span class="ph uicontrol" style="font-weight: bold;">Company Home > Data Dictionary > Transfers > Transfer Target Groups > Default Group</span>.</span>Create a folder for the new transfer target. For example, create a folder called <span class="ph uicontrol" style="font-weight: bold;">Transfer1</span>.<br />
<ol class="ol steps"></ol>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-Yhnh8HYeTf0/UzVqqa7mmPI/AAAAAAAAL6Y/xBj0mF11p8w/s1600/Screenshot+2014-03-28+17.52.44.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-Yhnh8HYeTf0/UzVqqa7mmPI/AAAAAAAAL6Y/xBj0mF11p8w/s1600/Screenshot+2014-03-28+17.52.44.png" height="360" width="640" /></a></div>
<div>
<br /></div>
<span class="ph cmd">Edit the properties for the <b>Transfer1 </b>and modify the following fields:</span><br />
<div class="taskinfo" style="margin-bottom: 0.4em; margin-top: 0.4em;">
<a href="https://www.blogger.com/null" name="adminconsole-replication-transfertarget__simpletable_pcx_jsw_tb" shape="rect" style="color: #2b6eb5;"></a><br />
<table border="1" cellpadding="4" cellspacing="0" class="simpletable" id="adminconsole-replication-transfertarget__simpletable_pcx_jsw_tb" style="border: 1pt solid rgb(116, 118, 121); empty-cells: show;" summary=""><tbody>
<tr class="sthead"><th align="left" class="stentry" colspan="1" id="d11079e101" rowspan="1" style="background-color: #cccccc; border: 1pt solid rgb(116, 118, 121); color: #333333; padding: 5pt;" valign="bottom">Field</th><th align="left" class="stentry" colspan="1" id="d11079e104" rowspan="1" style="background-color: #cccccc; border: 1pt solid rgb(116, 118, 121); color: #333333; padding: 5pt;" valign="bottom">What is it?</th></tr>
<tr class="strow"><td class="stentry" colspan="1" headers="d11079e101" rowspan="1" style="border: 1pt solid rgb(116, 118, 121); padding: 5pt;" valign="top"><span class="ph uicontrol" style="font-weight: bold;">Endpoint Host</span></td><td class="stentry" colspan="1" headers="d11079e104" rowspan="1" style="border: 1pt solid rgb(116, 118, 121); padding: 5pt;" valign="top">Type the host name of the target server.</td></tr>
<tr class="strow"><td class="stentry" colspan="1" headers="d11079e101" rowspan="1" style="border: 1pt solid rgb(116, 118, 121); padding: 5pt;" valign="top"><span class="ph uicontrol" style="font-weight: bold;">Endpoint Port</span></td><td class="stentry" colspan="1" headers="d11079e104" rowspan="1" style="border: 1pt solid rgb(116, 118, 121); padding: 5pt;" valign="top">Type the port number of the target server. For example, type <samp class="ph codeph">8080</samp>.</td></tr>
<tr class="strow"><td class="stentry" colspan="1" headers="d11079e101" rowspan="1" style="border: 1pt solid rgb(116, 118, 121); padding: 5pt;" valign="top"><span class="ph uicontrol" style="font-weight: bold;">User Name</span></td><td class="stentry" colspan="1" headers="d11079e104" rowspan="1" style="border: 1pt solid rgb(116, 118, 121); padding: 5pt;" valign="top">Type a user name of an account on the target server.</td></tr>
<tr class="strow"><td class="stentry" colspan="1" headers="d11079e101" rowspan="1" style="border: 1pt solid rgb(116, 118, 121); padding: 5pt;" valign="top"><span class="ph uicontrol" style="font-weight: bold;">Password</span></td><td class="stentry" colspan="1" headers="d11079e104" rowspan="1" style="border: 1pt solid rgb(116, 118, 121); padding: 5pt;" valign="top">Type a password for the user account.</td></tr>
<tr class="strow"><td class="stentry" colspan="1" headers="d11079e101" rowspan="1" style="border: 1pt solid rgb(116, 118, 121); padding: 5pt;" valign="top"><span class="ph uicontrol" style="font-weight: bold;">Enabled</span></td><td class="stentry" colspan="1" headers="d11079e104" rowspan="1" style="border: 1pt solid rgb(116, 118, 121); padding: 5pt;" valign="top">Click this checkbox to enable the transfer target.</td></tr>
</tbody></table>
</div>
<div class="taskstepresult" style="margin-bottom: 0.4em; margin-top: 0.4em;">
A rule defined on the <span class="ph uicontrol" style="font-weight: bold;">Default Group</span> folder specializes the type of any folder created within it. The type of the folder is set to <samp class="ph codeph">trx:transferTarget</samp>, which you can then complete through the user interface. </div>
<h1 class="title topictitle1" style="background-color: white; color: #00ae42; font-size: 18pt; font-weight: normal; margin-bottom: 0.6em; margin-top: 0pc;">
<span style="font-size: 18pt;">Configure Share to open locked content.</span></h1>
</div>
<div class="body taskbody" style="color: #333333; font-family: Helvetica; font-size: 15px;">
<ol class="ol steps" style="background-color: white;">
<li class="li step" style="margin-bottom: 0.6em; margin-top: 0.6em; text-align: left;"><span class="ph cmd">Locate the <samp class="ph codeph">repositoryId</samp> by browsing to the remote server's CMIS landing page using the following URL:</span><div class="taskinfo" style="margin-bottom: 0.4em; margin-top: 0.4em;">
<pre class="pre codeblock" style="background-color: #eeeeee; border: 1px solid rgb(116, 118, 121); color: inherit; font-size: 10pt; padding: 2px;" xml:space="preserve">http://{server}:{port}/alfresco/service/cmis/index.html</pre>
<div class="p" style="margin-top: 1em;">
The <samp class="ph codeph">repositoryId</samp> field is displayed in the <span class="ph uicontrol" style="font-weight: bold;">CMIS Repository Information</span> panel.</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-BLK7tJ4hkkQ/UzVMl0wYxmI/AAAAAAAAL6I/IVf_04Uhm8s/s1600/Screenshot+2014-03-28+15.46.33.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="Alfreso CMIS Content Repository" border="0" src="http://4.bp.blogspot.com/-BLK7tJ4hkkQ/UzVMl0wYxmI/AAAAAAAAL6I/IVf_04Uhm8s/s1600/Screenshot+2014-03-28+15.46.33.png" height="388" title="Alfreso CMIS Content Repository" width="640" /></a></div>
</div>
</li>
<li class="li step" style="margin-bottom: 0.6em; margin-top: 0.6em; text-align: left;"><span class="ph cmd">Open the <span class="ph filepath" style="font-family: monospace;"><web-extension>\share-config-custom.xml.sample</span> file.</span></li>
<li class="li step" style="margin-bottom: 0.6em; margin-top: 0.6em; text-align: left;"><span class="ph cmd">Locate the following example configuration:</span><div class="taskinfo" style="margin-bottom: 0.4em; margin-top: 0.4em;">
<pre class="pre codeblock" style="background-color: #eeeeee; border: 1px solid rgb(116, 118, 121); color: inherit; font-size: 10pt; padding: 2px;" xml:space="preserve"> <config evaluator="string-compare" condition="Replication">
<share-urls>
<!--
To discover a Repository Id, browse to the remote server's CMIS landing page at:
http://{server}:{port}/alfresco/service/cmis/index.html
The Repository Id field is found under the "CMIS Repository Information" expandable panel.
Example config entry:
<share-url repositoryId="622f9533-2a1e-48fe-af4e-ee9e41667ea4">http://new-york-office:8080/share/</share-url>
-->
</share-urls>
</config></pre>
</div>
</li>
<li class="li step" style="margin-bottom: 0.6em; margin-top: 0.6em; text-align: left;"><span class="ph cmd">Modify the <samp class="ph codeph">share-url repositoryId</samp> tag with the remote server's <samp class="ph codeph">repositoryId</samp> value, plus the remote server's URL.</span><div class="taskinfo" style="margin-bottom: 0.4em; margin-top: 0.4em;">
<div class="p" style="margin-top: 1em;">
For example:</div>
<pre class="pre codeblock" style="background-color: #eeeeee; border: 1px solid rgb(116, 118, 121); color: inherit; font-size: 10pt; padding: 2px;" xml:space="preserve"><share-url repositoryId="622f9533-2a1e-48fe-af4e-ee9e41667ea4">http://new-york-office:8080/share/</share-url></pre>
</div>
</li>
<li class="li step" style="margin-bottom: 0.6em; margin-top: 0.6em; text-align: left;"><span class="ph cmd">Save the sample file without the <span class="ph filepath" style="font-family: monospace;">.sample</span> extension, or alternatively, you can copy this configuration setting directly to your<span class="ph filepath" style="font-family: monospace;">share-config-custom.xml</span> file.</span></li>
<li class="li step" style="margin-bottom: 0.6em; margin-top: 0.6em; text-align: left;"><span class="ph cmd">Restart the Alfresco server.</span></li>
</ol>
</div>
<div class="body taskbody" style="color: #333333; font-family: Helvetica; font-size: 15px;">
<br /></div>
<div class="body taskbody" style="color: #333333; font-family: Helvetica; font-size: 15px;">
<br />
<ul>
<li>Verify that the target server is set up correctly.</li>
<li>Log in to the source server.</li>
<li>Create a folder on the source server.</li>
<li>For example, in Company Home, create <span class="ph uicontrol" style="font-weight: bold;">Folder1</span>.</li>
<li>Create a job with the source as <span class="ph uicontrol" style="font-weight: bold;">Folder1</span> and a transfer target as <span class="ph uicontrol" style="font-weight: bold;">Transfer1</span>. Refer to <a class="xref" href="http://docs.alfresco.com/4.1/topic/com.alfresco.enterprise.doc/tasks/adminconsole-replication-create.html" shape="rect" style="color: #2b6eb5; text-decoration: none;" title="You can create any number of replication jobs to suit your needs.">Creating a new replication job</a>.</li>
</ul>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-FlTQlAP4K4s/UzXCmdjVGGI/AAAAAAAAL6w/-ejMfT-Alhk/s1600/Screenshot+2014-03-29+00.06.16.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-FlTQlAP4K4s/UzXCmdjVGGI/AAAAAAAAL6w/-ejMfT-Alhk/s1600/Screenshot+2014-03-29+00.06.16.png" height="378" width="640" /></a></div>
<div>
<br /></div>
<ul>
<li>Run the new job.</li>
<li>On the target server, open the folder that contains the source for the job (<span class="ph uicontrol" style="font-weight: bold;">Folder1</span>).</li>
<li>On the target server, click <span class="ph uicontrol" style="font-weight: bold;">View in Source Repository</span>.</li>
<li><span class="ph uicontrol" style="font-weight: bold;">Folder1</span><span style="font-weight: bold;"> opens in the source repository.</span></li>
</ul>
<div>
<br /></div>
<div>
</div>
</div>
</div>
<div class="blogger-post-footer">https://scontent-b-mxp.xx.fbcdn.net/hphotos-xap1/v/t1.0-9/10675541_896261013719814_5601513019470361090_n.jpg?oh=741b05a81becaae8bce36db141948a4a&oe=5531762A</div>Krutik Jayswalhttp://www.blogger.com/profile/16691396948811505379noreply@blogger.com0