{"id":5434,"date":"2016-03-19T05:29:14","date_gmt":"2016-03-19T05:29:14","guid":{"rendered":"http:\/\/www.jitendrazaa.com\/blog\/?p=5434"},"modified":"2016-03-19T05:37:26","modified_gmt":"2016-03-19T05:37:26","slug":"creating-custom-ant-plugin-or-task-in-java","status":"publish","type":"post","link":"https:\/\/www.jitendrazaa.com\/blog\/java\/creating-custom-ant-plugin-or-task-in-java\/","title":{"rendered":"Creating custom ANT plugin or Task in Java"},"content":{"rendered":"<p style=\"text-align: justify;\"><a href=\"https:\/\/www.jitendrazaa.com\/blog\/tag\/ant\/\">ANT <\/a>is very powerful and one of the most used tool in Java and other platforms like Salesforce. In Salesforce, ANT is officially used to deploy changes on instances using Metadata API. It is also integral part of\u00a0<a href=\"https:\/\/www.jitendrazaa.com\/blog\/tag\/continuous-integration\/\">Continuous Integration<\/a>. Even though, there are hundreds of\u00a0libraries\u00a0and ANT Tasks are available to use, however there are many scenarios where we need to create our own custom Task.<\/p>\n<p style=\"text-align: justify;\">I am using many custom ANT tasks in my projects and its very easy to create. For example, I have created automated data load process with custom ANT task, which is almost as powerful as of any paid <a href=\"https:\/\/www.jitendrazaa.com\/blog\/tag\/etl\/\">ETL <\/a>tool.<\/p>\n<p style=\"text-align: justify;\">In this blog post, We\u00a0will go through creation of very simple ANT plugin. We will create a custom ANT Task with nested tags\u00a0,\u00a0attributes and then print it on console. It shows that, we can read attribute passed in <strong>build.xml.<\/strong>\u00a0if we can read attribute, then writing any custom logic is not a big deal.<!--more--><\/p>\n<p>We are planning to build below ANT task<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;DemoTask description=&quot;Sample Attribute at Task level&quot;&gt; \r\n\t&lt;DemoEntry path=&quot;c:\\\\FilePath\\\\File.txt&quot; isFolderPath=&quot;false&quot; \/&gt;\r\n\t&lt;DemoEntry path=&quot;c:\\\\Folder&quot; isFolderPath=&quot;true&quot; \/&gt;\r\n&lt;\/DemoTask&gt;\r\n<\/pre>\n<p>Below image shows working of custom ANT plugin.<\/p>\n<figure id=\"attachment_5437\" aria-describedby=\"caption-attachment-5437\" style=\"width: 1292px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/i0.wp.com\/www.jitendrazaa.com\/blog\/wp-content\/uploads\/2016\/03\/Creating-ANT-plugin.gif?ssl=1\" rel=\"attachment wp-att-5437\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" class=\"wp-image-5437 size-full\" src=\"https:\/\/i0.wp.com\/www.jitendrazaa.com\/blog\/wp-content\/uploads\/2016\/03\/Creating-ANT-plugin.gif?resize=1292%2C652&#038;ssl=1\" alt=\"Create custom ANT Task in Java\" width=\"1292\" height=\"652\" \/><\/a><figcaption id=\"caption-attachment-5437\" class=\"wp-caption-text\">Create custom ANT Task in Java<\/figcaption><\/figure>\n<p style=\"text-align: justify;\">Task name would be <strong>DemoTask<\/strong>. It will have attribute named <strong>description<\/strong>. Multiple child tags by name <strong>DemoEntry<\/strong> is used to showcase how we can read child tags in custom ANT task.<\/p>\n<p style=\"text-align: justify;\">We need to add <a href=\"https:\/\/github.com\/JitendraZaa\/ANT_Demo_Plugin\/blob\/master\/jar\/ant.jar\">ANT library<\/a> in class-path of our project, so that we can reuse its library.<\/p>\n<p style=\"text-align: justify;\">First step is to create a simple POJO (Plain Old Java Object) class to represent nested tag\u00a0<strong>DemoEntry.\u00a0<\/strong>This class will have properties with setter and getters. In this case, we need two properties &#8211; &#8220;path&#8221; and &#8220;isFolderPath&#8221; as shown in below class.<\/p>\n<p><strong>DemoEntry.java<\/strong><\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n\/*\r\n * @Author  :   Jitendra Zaa\r\n * @Date    :   03\/18\/2016\r\n *\/\r\npackage com.jitendrazaa;\r\n \r\nimport java.util.Objects;\r\n\r\npublic class DemoEntry {\r\n \r\n    String path ;    \r\n    Boolean isFolderPath ;\r\n\r\n    public DemoEntry(){}\r\n    \r\n    public DemoEntry(String path, Boolean isFolderPath) {\r\n        this.path = path;\r\n        this.isFolderPath = isFolderPath;\r\n    } \r\n\r\n    public String getPath() {\r\n        return path;\r\n    }\r\n\r\n    public void setPath(String path) {\r\n        this.path = path;\r\n    }\r\n\r\n    public Boolean getIsFolderPath() {\r\n        return isFolderPath;\r\n    }\r\n\r\n    public void setIsFolderPath(Boolean isFolderPath) {\r\n        this.isFolderPath = isFolderPath;\r\n    }\r\n\r\n    @Override\r\n    public int hashCode() {\r\n        int hash = 7;\r\n        hash = 71 * hash + Objects.hashCode(this.path);\r\n        hash = 71 * hash + Objects.hashCode(this.isFolderPath);\r\n        return hash;\r\n    }\r\n\r\n    @Override\r\n    public boolean equals(Object obj) {\r\n        if (this == obj) {\r\n            return true;\r\n        }\r\n        if (obj == null) {\r\n            return false;\r\n        }\r\n        if (getClass() != obj.getClass()) {\r\n            return false;\r\n        }\r\n        final DemoEntry other = (DemoEntry) obj;\r\n        if (!Objects.equals(this.path, other.path)) {\r\n            return false;\r\n        }\r\n        if (!Objects.equals(this.isFolderPath, other.isFolderPath)) {\r\n            return false;\r\n        }\r\n        return true;\r\n    } \r\n}\r\n<\/pre>\n<p style=\"text-align: justify;\">Its time to create class which will act as custom ANT Task.<br \/>\n<strong>DemoTask.java<\/strong><\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n\/*\r\n * @Author  :   Jitendra Zaa\r\n * @Date    :   03\/18\/2016\r\n *\/\r\npackage com.jitendrazaa;\r\n\r\nimport java.io.PrintWriter;\r\nimport java.io.StringWriter;\r\nimport java.util.HashSet;\r\nimport java.util.Iterator;\r\n\r\nimport org.apache.tools.ant.Task;\r\n\r\npublic class DemoTask extends Task {\r\n\r\n    HashSet&lt;DemoEntry&gt; demoEntryList = new HashSet&lt;DemoEntry&gt;();\r\n    String description ;\r\n    \r\n    \/**\r\n     * print Stacktrace from Exception\r\n     * @param e\r\n     * @return \r\n     *\/\r\n    private String getExceptionMessage(Exception e) {\r\n        StringWriter sw = new StringWriter();\r\n        e.printStackTrace(new PrintWriter(sw));\r\n        return sw.toString();\r\n    }\r\n\r\n    \/**\r\n     * Create Method needed by Ant reflection\r\n     *\r\n     * @return\r\n     *\/\r\n    public DemoEntry createDemoEntry() {\r\n        DemoEntry item = new DemoEntry();\r\n        demoEntryList.add(item);\r\n        return item;\r\n    }\r\n\r\n    \/**\r\n     * We cannot use original &quot;demoEntryList&quot; because it is created with blank\r\n     * value and using java reflection values are populated. Hashset method is\r\n     * computed during constructor and any change in value after constructor\r\n     * will not change Hashset.\r\n     *\r\n     * @return HashSet&lt;DemoEntry&gt;\r\n     *\/\r\n    private HashSet&lt;DemoEntr&gt; cloneIgnoreSet() {\r\n        HashSet&lt;DemoEntry&gt; newSet = new HashSet&lt;DemoEntry&gt;();\r\n        for (Iterator&lt;DemoEntry&gt; it = demoEntryList.iterator(); it.hasNext();) {\r\n            DemoEntry item = it.next();\r\n            DemoEntry newItem = new DemoEntry(item.getPath(), item.getIsFolderPath());\r\n            newSet.add(newItem);\r\n            log(&quot; ------- Reading sub tag -------- &quot;);\r\n            log(&quot;Path - &quot;+item.getPath());\r\n            log(&quot;Is Folder Path - &quot;+item.getIsFolderPath());\r\n        }\r\n        return newSet;\r\n    }\r\n\r\n    public void execute() {\r\n        try {\r\n            log(&quot;Description - &quot;+getDescription());\r\n            \/\/Read set of tags from ANT Build script\r\n            HashSet&amp;lt;DemoEntry&amp;gt; setDemo = cloneIgnoreSet();\r\n        } catch (Exception e) {\r\n            log(getExceptionMessage(e));\r\n        }\r\n    }\r\n\r\n    public String getDescription() {\r\n        return description;\r\n    }\r\n\r\n    public void setDescription(String description) {\r\n        this.description = description;\r\n    }\r\n\r\n}\r\n<\/pre>\n<p style=\"text-align: justify;\">This custom ANT task class needs to extend org.apache.tools.ant.Task available in ANT library. Method createDemoEntry will be called by ANT to initialize nested tags. Method getDescription and setDescription is used to get and set attribute named Description. Remaining part of code is well documented.<\/p>\n<p style=\"text-align: justify;\">We can build above classes as a jar file either from Eclipse, Netbeans or Java command.<\/p>\n<p style=\"text-align: justify;\">To test this custom ANT task, lets create build.properties file. It is not necessary to create this in our example, however there is no harm in following best practices. This file has complete path of custom jar file.<\/p>\n<p style=\"text-align: justify;\"><strong>build.properties<\/strong><\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\npluginFileName=ANT_Plugin.jar\r\n<\/pre>\n<p><strong>Build.xml<\/strong><\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;project name=&quot;Demo ANT Plugin&quot; default=&quot;Demo&quot; basedir=&quot;.&quot;&gt;  \r\n    &lt;property file=&quot;build.properties&quot;\/&gt; \r\n\t&lt;target name=&quot;Demo&quot;&gt;  \r\n\t\t&lt;taskdef name=&quot;DemoTask&quot; classname=&quot;com.jitendrazaa.DemoTask&quot; classpath=&quot;${pluginFileName}&quot;\/&gt;\r\n\t\t&lt;DemoTask description=&quot;Sample Attribute at Task level&quot;&gt; \r\n            &lt;DemoEntry path=&quot;c:\\\\FilePath\\\\File.txt&quot; isFolderPath=&quot;false&quot; \/&gt;\r\n            &lt;DemoEntry path=&quot;c:\\\\Folder&quot; isFolderPath=&quot;true&quot; \/&gt;\r\n\t\t&lt;\/DemoTask&gt;\r\n\t&lt;\/target&gt;     \r\n&lt;\/project&gt;  \r\n<\/pre>\n<p>We can run above build file by either using command <em>ANT<\/em> or <em>ANT Demo<\/em>. Demo image above shows final output and custom ANT task in action. Complete source code is available on <a href=\"https:\/\/github.com\/JitendraZaa\/ANT_Demo_Plugin\">my Github account<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Tutorial to create custom Task in ANT with complete source code<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"advanced_seo_description":"","jetpack_seo_html_title":"","jetpack_seo_noindex":false,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"jz_research_post":"","_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[3],"tags":[261],"class_list":["post-5434","post","type-post","status-publish","format-standard","hentry","category-java","tag-ant"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":2892,"url":"https:\/\/www.jitendrazaa.com\/blog\/salesforce\/salesforce-migration-tool-ant\/","url_meta":{"origin":5434,"position":0},"title":"Complete Salesforce Deployment Guide using Ant Migration Tool","author":"Jitendra","date":"June 5, 2012","format":false,"excerpt":"Step by Step tutorial of Salesforce Migration using ANT tool with Proxy settings and retrieving content from Salesforce Organization. Also fix some common errors like java.lang.OutOfMemoryError or unable to find tools.jar","rel":"","context":"In &quot;Configuration&quot;","block_context":{"text":"Configuration","link":"https:\/\/www.jitendrazaa.com\/blog\/category\/salesforce\/configuration\/"},"img":{"alt_text":"Salesforce Get ANT version ","src":"https:\/\/i0.wp.com\/jitendrazaa.com\/blog\/wp-content\/uploads\/2012\/06\/Salesforce-Get-ANT-version-Original.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/jitendrazaa.com\/blog\/wp-content\/uploads\/2012\/06\/Salesforce-Get-ANT-version-Original.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/jitendrazaa.com\/blog\/wp-content\/uploads\/2012\/06\/Salesforce-Get-ANT-version-Original.png?resize=525%2C300&ssl=1 1.5x"},"classes":[]},{"id":4431,"url":"https:\/\/www.jitendrazaa.com\/blog\/salesforce\/using-dataloader-and-ant-to-backup-salesforce-data-on-ftp-server-video\/","url_meta":{"origin":5434,"position":1},"title":"Using Dataloader and ANT to backup Salesforce data on FTP or SFTP server &#8211; Video","author":"Jitendra","date":"May 4, 2015","format":false,"excerpt":"Tutorial on how to use command line dataloader to save exported Salesforce backup file on FTP or SFTP server","rel":"","context":"In &quot;Salesforce&quot;","block_context":{"text":"Salesforce","link":"https:\/\/www.jitendrazaa.com\/blog\/category\/salesforce\/"},"img":{"alt_text":"Use Dataloader and ANT to back CSV file on FTP Server","src":"https:\/\/i0.wp.com\/www.jitendrazaa.com\/blog\/wp-content\/uploads\/2015\/05\/Use-Dataloader-and-ANT-to-back-CSV-file-on-FTP-Server-1024x391.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.jitendrazaa.com\/blog\/wp-content\/uploads\/2015\/05\/Use-Dataloader-and-ANT-to-back-CSV-file-on-FTP-Server-1024x391.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.jitendrazaa.com\/blog\/wp-content\/uploads\/2015\/05\/Use-Dataloader-and-ANT-to-back-CSV-file-on-FTP-Server-1024x391.png?resize=525%2C300&ssl=1 1.5x"},"classes":[]},{"id":6209,"url":"https:\/\/www.jitendrazaa.com\/blog\/salesforce\/how-to-retrieve-and-deploy-custom-metadata-types-using-ant\/","url_meta":{"origin":5434,"position":2},"title":"How to Retrieve and Deploy Custom Metadata Types using ANT","author":"Jitendra","date":"August 27, 2017","format":false,"excerpt":"Using Salesforce ANT Migration toolkit to retrieve and deploy custom metadata types with record. Sample Package.xml and ANT script included.","rel":"","context":"In &quot;Salesforce&quot;","block_context":{"text":"Salesforce","link":"https:\/\/www.jitendrazaa.com\/blog\/category\/salesforce\/"},"img":{"alt_text":"Sample of Package.xml to deploy Custom Metadata Types","src":"https:\/\/i0.wp.com\/www.jitendrazaa.com\/blog\/wp-content\/uploads\/2017\/08\/Sample-of-Package.xml-to-deploy-Custom-Metadata-Types.png?fit=1051%2C330&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.jitendrazaa.com\/blog\/wp-content\/uploads\/2017\/08\/Sample-of-Package.xml-to-deploy-Custom-Metadata-Types.png?fit=1051%2C330&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.jitendrazaa.com\/blog\/wp-content\/uploads\/2017\/08\/Sample-of-Package.xml-to-deploy-Custom-Metadata-Types.png?fit=1051%2C330&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.jitendrazaa.com\/blog\/wp-content\/uploads\/2017\/08\/Sample-of-Package.xml-to-deploy-Custom-Metadata-Types.png?fit=1051%2C330&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/www.jitendrazaa.com\/blog\/wp-content\/uploads\/2017\/08\/Sample-of-Package.xml-to-deploy-Custom-Metadata-Types.png?fit=1051%2C330&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":4276,"url":"https:\/\/www.jitendrazaa.com\/blog\/salesforce\/continuous-integration-in-salesforce-using-jenkins-and-git-video-tutorial\/","url_meta":{"origin":5434,"position":3},"title":"Continuous integration in Salesforce Using Jenkins and Git | Video Tutorial","author":"Jitendra","date":"March 23, 2015","format":false,"excerpt":"As your Salesforce Organization undergoes heavy customization and frequent builds, moving changes from one Sandbox to other sandboxes starts taking longer time and effort. Also, in normal Salesforce project, there are chances that you will have minimum three sandboxes likely Developer Sandbox, QA Sandbox and UAT Sandbox. After some time\u2026","rel":"","context":"In &quot;Salesforce&quot;","block_context":{"text":"Salesforce","link":"https:\/\/www.jitendrazaa.com\/blog\/category\/salesforce\/"},"img":{"alt_text":"Salesforce - Jenkins Git Polling Log","src":"https:\/\/i0.wp.com\/www.jitendrazaa.com\/blog\/wp-content\/uploads\/2015\/03\/Salesforce-Jenkins-Git-Polling-Log.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.jitendrazaa.com\/blog\/wp-content\/uploads\/2015\/03\/Salesforce-Jenkins-Git-Polling-Log.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.jitendrazaa.com\/blog\/wp-content\/uploads\/2015\/03\/Salesforce-Jenkins-Git-Polling-Log.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/www.jitendrazaa.com\/blog\/wp-content\/uploads\/2015\/03\/Salesforce-Jenkins-Git-Polling-Log.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":3902,"url":"https:\/\/www.jitendrazaa.com\/blog\/salesforce\/automated-daily-backup-using-ant-migration-tool-and-git\/","url_meta":{"origin":5434,"position":4},"title":"Automated Daily Backup of Salesforce Using ANT Migration Tool and GIT","author":"Jitendra","date":"July 5, 2014","format":false,"excerpt":"In few\u00a0previous articles, I have talked about how to use \"ANT Migration tool in Salesforce\" and \"How to Use EGit plugin in Eclipse to work with Git\". So to make this article short, I assume that you are already familiar with ANT Migration tool provided by Salesforce and Git. During\u2026","rel":"","context":"In &quot;Configuration&quot;","block_context":{"text":"Configuration","link":"https:\/\/www.jitendrazaa.com\/blog\/category\/salesforce\/configuration\/"},"img":{"alt_text":"Salesforce Automated Script for Data Backup Using CommandLine","src":"https:\/\/i0.wp.com\/www.jitendrazaa.com\/blog\/wp-content\/uploads\/2014\/07\/Salesforce-Automated-Script-for-Data-Backup-Using-CommandLine.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.jitendrazaa.com\/blog\/wp-content\/uploads\/2014\/07\/Salesforce-Automated-Script-for-Data-Backup-Using-CommandLine.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.jitendrazaa.com\/blog\/wp-content\/uploads\/2014\/07\/Salesforce-Automated-Script-for-Data-Backup-Using-CommandLine.png?resize=525%2C300&ssl=1 1.5x"},"classes":[]},{"id":5478,"url":"https:\/\/www.jitendrazaa.com\/blog\/salesforce\/delete-components-using-ant-migration-tool-video\/","url_meta":{"origin":5434,"position":5},"title":"Delete Components using Ant Migration tool &#8211; Video","author":"Jitendra","date":"April 27, 2016","format":false,"excerpt":"This video tutorial shows that how we can delete components like Apex class, trigger from Salesforce using ANT migration tool.","rel":"","context":"In &quot;Salesforce&quot;","block_context":{"text":"Salesforce","link":"https:\/\/www.jitendrazaa.com\/blog\/category\/salesforce\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/img.youtube.com\/vi\/3kMGy6OeJAc\/0.jpg?resize=350%2C200","width":350,"height":200},"classes":[]}],"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/www.jitendrazaa.com\/blog\/wp-json\/wp\/v2\/posts\/5434","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.jitendrazaa.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.jitendrazaa.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.jitendrazaa.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.jitendrazaa.com\/blog\/wp-json\/wp\/v2\/comments?post=5434"}],"version-history":[{"count":6,"href":"https:\/\/www.jitendrazaa.com\/blog\/wp-json\/wp\/v2\/posts\/5434\/revisions"}],"predecessor-version":[{"id":5441,"href":"https:\/\/www.jitendrazaa.com\/blog\/wp-json\/wp\/v2\/posts\/5434\/revisions\/5441"}],"wp:attachment":[{"href":"https:\/\/www.jitendrazaa.com\/blog\/wp-json\/wp\/v2\/media?parent=5434"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.jitendrazaa.com\/blog\/wp-json\/wp\/v2\/categories?post=5434"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.jitendrazaa.com\/blog\/wp-json\/wp\/v2\/tags?post=5434"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}