Version 7

    Publish Drools artifacts from a production environment

    Enterprise people often want a production repository that is physically separated from development repository. One approach to address this requirement is to automatically pull published artifacts from development repository then copy them to a http server. As Guvnor already has the capability of publishing artifacts through its REST interface, what we really need is a simple copy script that copies published artifacts from Guvnor dev repository to a HTTP server based on certain metadata for example lifecycle state. Following example shows how to do this with a Java client.


    1. Subscribe to Guvnor package versions feed:


    The version feed is published in Atom format. Its URL is http://server:port/guvnor-webapp/rest/packages/PACKAGENAME/versions.


    2. Poll package version feed periodically. When a new version of package is available, the client can ask Guvnor to send it back an Atom Entry which contains detailed package metadata for this version. Based on package metadata (for example,  lifecycle state or categories), the client pulls package binary from Guvnor then save they to a configured location on the HTTP server.


    Here is an example code:


    public class AtomClient extends TimerTask {

        private Date lastUpdateDate;

        private String feedURL;


        public AtomClient(String feedURL) {

            this.feedURL = feedURL;



        public void run() {

            try {

                System.out.println("-------Polling feed------");

                List<Entry> entries = createFeed().getEntries();

                for (Entry entry : entries) {

                    if (isEntryUpdated(entry)) {

                        String title = entry.getTitle();

                        System.out.println("-------Found a new entry ------");

                        System.out.println("Title: " + title);

                        System.out.println("Updated: " + entry.getUpdated());

                        String contentSrcPath = entry.getLinks().get(0).getHref().toString();

                        InputStream is = getPackageBinary(contentSrcPath);


                        String NS = "";

                        QName METADATA = new QName(NS, "metadata");

                        QName STATE = new QName(NS, "stage");

                        ExtensibleElement metadataExtension  = entry.getExtension(METADATA);

                        String state = metadataExtension.getSimpleExtension(STATE);

                        System.out.println("state: " + state);

                        //We can copy package binary to different locations based on state info.



                        File f = new File(title + ".pkg");

                        OutputStream out = new FileOutputStream(f);


                        int read = 0;

                        byte[] bytes = new byte[1024];

                        while ((read = != -1) {

                            out.write(bytes, 0, read);








            } catch (Exception e) {





        private Feed createFeed() throws IOException {

            Abdera abdera = new Abdera();

            AbderaClient client = new AbderaClient(abdera);

            ClientResponse resp = client.get(feedURL);

            if (resp.getType() == ResponseType.SUCCESS) {

              Document<Feed> doc = resp.getDocument();

              return doc.getRoot();

            } else {

              // there was an error

              return null;




        private InputStream getPackageBinary(String contentSrcPath) throws IOException {

            Abdera abdera = new Abdera();

            AbderaClient client = new AbderaClient(abdera);

            ClientResponse resp = client.get(contentSrcPath+"/source");

            return resp.getInputStream();



        private boolean isEntryUpdated(Entry entry) {

            Date updateDate = entry.getUpdated();

            if (updateDate == null) {

                updateDate = entry.getPublished();


            if (updateDate == null) {

                return true;



            if (lastUpdateDate != null && (updateDate.before(lastUpdateDate) || updateDate.equals(lastUpdateDate))) {

                return false;


            lastUpdateDate = updateDate;

            return true;     



        public static void main(String[] args) {

            int pollingInterval = 60;

            String feedURL = "http://localhost:8080/guvnor-webapp/rest/packages/mortgages/versions";

            AtomClient atomTask = new AtomClient(feedURL);

            Timer timer = new Timer();

            timer.schedule(atomTask, 1000, pollingInterval * 1000);






    Package versions feed example:

    <feed xml:base="http://localhost:9080/drool-guvnor/rest/packages/mortgage/versions">

       <title>Versions of testPackage1</title>

       <entry xml:base="http://localhost:9080/drool-guvnor/rest/packages/mortgage/versions">



         <link href="http://localhost:9080/drool-guvnor/rest/packages/mortgage/versions/2"/>



       <entry xml:base="http://localhost:9080/drool-guvnor/rest/packages/mortgage/versions">



         <link href="http://localhost:9080/drool-guvnor/rest/packages/mortgage/versions/1"/>




    Package Entry example:

    <entry xml:base="http://localhost:9080/drools-guvnor/rest/packages/mortage/versions/2">



      <summary>desc of testRule1</summary>


        <property name="archived" value="false" />

        <property name="state" value="DEV" />



      <link href="http://localhost:9080/drools-guvnor/rest/packages/testPackage1/assets/testRule1/versions/1" title="testRule1"/>

      <link href="http://localhost:9080/drools-guvnor/rest/packages/testPackage1/assets/testRule2/versions/2" title="testRule2"/>


      <content type="application/octet-stream" src="http://localhost:9080/drools-guvnor/rest/packages/mortage/versions/2/binary"/>