How to add or remove xml elements in API during the deployment using Maven plugin,

Not applicable

I am converting a API bundle to maven dependent bundle to automate the build and deployment. I have a requirement to add and remove the virtual hosts in proxies for different environments. For example. Test environment have default and Prod environment must have default and secure virtual hosts. I tried to add this through configuration in config.json but it could work. As config.json file converts all the values into text format and the xml tags will be parsed to corresponding characters (ex. < to <). Even escape characters does not work as each value is parsed to normal text. Is there way to change the xml elements using maven configuration.

Solved Solved
0 10 1,399
1 ACCEPTED SOLUTION

Not applicable

I just verified that you can have the same Virtual host defined twice in the proxy.xml definition without error. This means you could have multiple elements defined as "default" and for your prod instance change the first entry to "secure" via config.json. This would achieve your goal - though it is not an ideal solution.

View solution in original post

10 REPLIES 10

Not applicable

Hi @Kalmesh. Is there any compelling reason not to have both virtual hosts in test environment? As a best practice, we usually recommend removing default virtual host for prod environment due as its insecure nature as it's http, so there's no encryption over the wire.

If you still need to implement it on Maven, I think you can achieve this by having two files. One for prod with default and secure and one for test with only default virtual host. Then you could rename the file leveraging some maven-ant-run plugin. I'm not an expert on Maven, but it should be doable. But frankly, it also depends on how advanced you're on this, you could achieve the same capability leveraging other build tools such as Grunt Plugin in a more elegant way.

Not applicable

Hi @Diego Zuluaga Thanks for response. We do have four different environments and requirement is to have different vhosts for each, also some other xml elements. Can not change the current implementation. The approach you suggested is good to implement but there are several files and we can not make duplicate of all.Thanks once again.

Not applicable

If you are using the Maven deployment plugin you have the opportunity to do value changes at deploy time based on your target environment. The config.json file in the apiproxy directory defines these substitutions.

Here is a sample that changes the virtual host and base path:

{
    "configurations": [{
        "name": "dev",
        "policies": [],
        "proxies": [{
            "name": "default.xml",
            "tokens": [{
                "value": "/basepath-sample-your-basepath-here",
                "xpath": "/ProxyEndpoint/HTTPProxyConnection/BasePath"
            }, {
                "value": "secure",
                "xpath": "/ProxyEndpoint/HTTPProxyConnection/VirtualHost"
            }]
        }],
        "targets": []
    }, {
        "name": "intg",
        "policies": [],
...

Any XML file in your bundle (target definitions, proxy definitions, policies) can be modified at deploy time using this approach.

Hope this helps!

Hi David, I think Kalmesh is looking for removing an element instead of changing the value of an element, which is what you suggested. I think another option although requires more work, it is to implement a mojo that removes the element.

Hi @David Allen The example you shared changes the existing value to secure. But my requirement is to add new Virtualhost element. For example.

Test env has "default" host.

<HTTPProxyConnection><VirtaulHost>default</VirtaulHost> </HTTPProxyConnection>

And I want to add new host "secure" in prod.

<HTTPProxyConnection><VirtaulHost>default</VirtaulHost> <VirtaulHost>secure</VirtaulHost></HTTPProxyConnection>

Is this possible to add new element using config.json?

Thanks.

Not applicable

No you would not be able to Add an element only change an existing one. In the case you describe we typically create the elements in the proxy definition with dummy data and then provide a config.json entry for every environment that populates it with the intended values. I.e.:

    <HTTPProxyConnection>
        <BasePath>basepath set by config.json</BasePath>
        <VirtualHost>virtualhost set by config.json</VirtualHost>
    </HTTPProxyConnection>

In your case you want to have multiple VirtualHost definitions - that is not a case that I have experimented with. I will take a look at the problem when I get some free cycles today and see if I can come up with a solution.

Not applicable

I just verified that you can have the same Virtual host defined twice in the proxy.xml definition without error. This means you could have multiple elements defined as "default" and for your prod instance change the first entry to "secure" via config.json. This would achieve your goal - though it is not an ideal solution.

Good idea! This seems good enough to overcome the issue. Another suggestion, although not the fastest route as yours is to write a Maven Mojo that removes the element before generating the zip file.

I think I prefer your grunt suggestion from another post more. That would allow for a full block replacement. @@VirtualHosts@@ could be rewritten from that job. I need to get more experience with that approach.

Agreed. Just in case anyone wants to take a first stab at a Grunt plugin. Here's a snippet of code to demonstrate a PoC (Proof of Concept) of doing it in Node.js:

var libxmljs = require("libxmljs");
var xml =  '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' +
'<ProxyEndpoint name="default">' +
    '<Description/>' +
    '<FaultRules/>' +
    '<Flows>' +
        '<Flow name="/hello-get">' +
            '<Description/>' +
            '<Request/>' +
            '<Response/>' +
            '<Condition>(proxy.pathsuffix MatchesPath "/hello") and (request.verb = "get")</Condition>' +
        '</Flow>' +
    '</Flows>' +
    '<HTTPProxyConnection>' +
        '<BasePath>/test-apigeetool</BasePath>' +
        '<Properties/>' +
        '<VirtualHost>secure</VirtualHost>' +
        '<VirtualHost>default</VirtualHost>' +
    '</HTTPProxyConnection>' +
    '<RouteRule name="default">' +
        '<TargetEndpoint>default</TargetEndpoint>' +
    '</RouteRule>' +
'</ProxyEndpoint>';


var xmlDoc = libxmljs.parseXml(xml);


xmlDoc.find('//VirtualHost')[0].remove(); // 0 to remove default, 1 to remove secure
console.log(xmlDoc.toString()); // This will print only default VirtualHost