Pattern-type (Part 22): Create a component which doesn’t generate a VM.

In the previous article (here), I explained how to create a component that generates one or more VMs. In this one, I will explain a method to create a component which doesn’t generate VM but interacts with another one via a link. You can find a use case of this in the WebApp pattern where you are able to add extra “archive file” to a WAS via the “Extra Archive File” component.The scenario is: Create a component that will inject parameters in an “Enterprise Application Server”.

The steps are:
1) Create the plugin.
2) Create a component and a link in the application model.
3) Create an OSGi service component for a Java based transformation.
4) Implement the Java class.
5) Add packages.

1. Create the plugin
Use the “Plugin Wizard” to create a new plugin and set the “webapp” pattern-type as primary pattern-type in the config.json.

{
    "name": "pluginOneCompNoVM",
    "version": "1.0.0.0",
    "patterntypes": {
        "secondary": {
        	"webapp":"*"
        }
    }
}

2. Create a component and a link in the application model.
As usual use the metadata.json editor to create a new component and a link to the “EAR” Role.

[
   {
      "id": "externalResource",
      "type": "component",
      "label": "External Resource",
      "attributes": [
         {
            "id": "externalResourceAttr",
            "type": "string",
            "required": false,
            "label": "External Resource Attribute"
         }
      ]
   },
   {
      "id": "externalResource",
      "type": "link",
      "source": [
         "externalResource"
      ],
      "target": [
         "EAR"
      ],
      "label": "External Resource Link",
      "description": "This link an external resouce component to a WAS",
      "attributes": [
         {
            "id": "externalResourceLinkAttr",
            "type": "string",
            "required": false,
            "label": "External Resource Link Attribute"
         }
      ]
   }
]

You can see I added 2 attributes one on the component and one on the link. We will push these attributes in the WAS topology.

3. Create an OSGi service component for a Java based transformation.
Use the wizard for that (“OSGi Service Component”), the wizard will create a skeleton for your class, create the OSGi Service Component file and update the MANIFEST.INF where the OSGi file will be inserted and the Java package will be exported.
SCAWS plugin.onecomp.novm OSGI WizardPS: As my “externalresource.xml” already exists, I add a “2” and this just to take the screenshot and avoid error messages.
The OSGI file looks like:
<?xml version=”1.0″ encoding=”UTF-8″?>
xmlns:scr=”http://www.osgi.org/xmlns/scr/v1.1.0″ name=”externalResource”>;
<implementation />;
<service>
<provide interface=”com.ibm.maestro.model.transform.TopologyProvider” />
</service>
</scr:component>

and a Java class has been created with 2 methods to implement.
Also the MANIFEST.INF has been updated.

4. Implement the Java class.
In the Java class we have to implement the transformComponent method (the component being our externalResource) and the transformLink method (the link being the link between the externalResource and the EAR component).
Now the sky is the limit, but one trick to know is that you can pass values from one method to another via the context. The transformComponent method return a JSONObject, the content of this object will be copied in the component context and you can retrieve it in the transformLink from the sourceComponent.
For example:

	@Override
	public JSONObject transformComponent(String vmTemplateNamePrefix,
			String applicationUrl, JSONObject applicationComponent,
			Transformer transformer) throws Exception {
		JSONObject attributes = (JSONObject) applicationComponent.get("attributes");
		JSONObject result = new JSONObject();
		result.put("service",attributes);
		return result;
	}

and

	@Override
	public void transformLink(JSONObject sourceFragment,
			JSONObject targetFragment, String applicationUrl,
			JSONObject applicationLink, Transformer transformer)
			throws Exception {
		MatchedRole target = getMatchedRole(targetFragment, "WAS");
		JSONObject parms = (JSONObject) target.role.get("parms");
		JSONObject serviceParms = (JSONObject) sourceFragment.get("service");
		parms.putAll(serviceParms);
		JSONObject attributes = (JSONObject) applicationLink.get("attributes");
		parms.putAll(attributes);

	}

5. Add packages.
In the transformLink method implementation you can also insert package in the target topology, for example to run the setup of your externalResource in the WAS role. For that you have to retrieve the “packages” JSONObject from the target template and add your own package in it. Of course, you already declare this package in your config.json.