WSO2 Programmatically Update an Endpoint Configuration - wso2

I wrote these code lines for accessing and modifying programmatically the load balanced endpoint configurations saved in my esb (4.7.0) local registry. [in a few words i add a new address endpoint to the load balance endpoint list]
SynapseConfiguration sc = synapseMsgContext.getConfiguration();
LoadbalanceEndpoint le =(LoadbalanceEndpoint) sc.getEndpoint("test");
List<Endpoint>list = le.getChildren();
AddressEndpoint ad = new AddressEndpoint();
EndpointDefinition def = new EndpointDefinition();
def.setAddress("http://172.17.54.101:8083/RestService/rest/servizio");
def.setAddressingOn(false);
def.setTimeoutAction(100);
ad.setDefinition(def);
list.add(ad);
le.setChildren(list);
sc.updateEndpoint("test", le);
synapseMsgContext.setConfiguration(sc);
By this code lines the endpoint's updates are held in memory and lost when i restart the ESB. So this update lastes only till the esb is stopped.
How can i make these updates persistent? I mean an effective update on the endpoint xml configuration file?

You have to check endpoint serilaizer and factory.
http://svn.wso2.org/repos/wso2/carbon/platform/branches/turing/dependencies/synapse/2.1.2-wso2v3/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/

Related

Get service Name of Task under aws fargate

We need to get the service name under which a fargate task runs so we can perform some per service configuration (we have one service per customer, and use the service name to identify them).
By knowing the service discovery namespace for our cluster and the Task IP address, we are able to do find out the service by doing the following.
Get the task ip address, eaither by calling http://169.254.170.2/v2/metadata endpoint or by using the ECS_ENABLE_CONTAINER_METADATA method in my follow-up answer.
With the cluster namespace we call AWS.ServiceDiscovery.listNamespaces
From there we extract the nameSpace id.
We pass that to AWS.ServiceDiscovery.listServices
We pass the id of each service to AWS.ServiceDiscovery.listInstances
We flat map the results of that and look for an instance that matches our IP address above.
VoilĂ ! that record gives us the service name.
Works fine, it just seems like a super circuitous path! I'm just wondering whether there is some shorter way to get this information.
Here's a working C# example in two steps. It gets the taskARN from the metadata to retrieve the task description, and then reads its Group property, which contains the name of the service. It uses AWSSDK.ECS to get the task description and Newtonsoft.Json to parse the JSON.
private static string getServiceName()
{
// secret keys, should be encoded in license configuration object
var ecsClient = new AmazonECSClient( ACCESS_KEY, SECRET_KEY );
var request = new DescribeTasksRequest();
// need cluster here if not default
request.Cluster = NAME_OF_CLUSTER;
request.Tasks.Add( getTaskArn() );
var asyncResponse = ecsClient.DescribeTasksAsync( request );
// probably need this synchronously for application to proceed
asyncResponse.Wait();
var response = asyncResponse.Result;
string group = response.Tasks.Single().Group;
// group returned in the form "service:[NAME_OF_SERVICE]"
return group.Remove( 0, 8 );
}
private static string getTaskArn()
{
// special URL for fetching internal Amazon information for ECS instances
string url = #"http://169.254.170.2/v2/metadata";
string metadata = getWebRequest( url );
// use JObject to read the JSON return
return JObject.Parse( metadata )[ "TaskARN" ].ToString();
}
private static string getWebRequest( string url )
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create( url );
request.AutomaticDecompression = DecompressionMethods.GZip;
using HttpWebResponse response = (HttpWebResponse)request.GetResponse();
using Stream stream = response.GetResponseStream();
using StreamReader reader = new StreamReader( stream );
return reader.ReadToEnd();
}
You can get the service name from startedBy property of the task definition. Using boto sdk you can call a describe_tasks (or its equivalent in aws-cli: aws ecs describe-tasks) which will provide a
'startedBy': 'string'
The tag specified when a task is started. If the task is started by an Amazon ECS service, then the startedBy parameter contains the deployment ID of the service that starts it.
From:
boto3 ecs client
aws-cli ecs client
Hope it helps.
The answer above requires reading the container metadata that appears if you set the ECS_ENABLE_CONTAINER_METADATA environment variable in the task. The work flow is then:
Read the container metadata file ecs-container-metadata.json to get the taskArn
Call the aws.ecs.describe-tasks function to get the startedBy property
Call aws.servicediscover.get-service.
Two steps instead of three, if you don't count reading the metadata file. Better, to be sure, but I'm probably not going to change the way we do it for now.

APIM191 - "Status Report - Not Found" In a distribuited setup.

I have a distributed setup (WSO2 APIM 191) like this:
2 servers working with store and pubisher in cluster; (Server A and B);
2 servers working with gateway-workers and keymanager in cluster; (Server C and D);
1 server working as gateway-manager; (Server E);
1 server working with a BAM; (Server F);
2 postgres in cluster;
All is configured and works well. But when I registry a API at "A" this API is not shown by the server "C" or "D".
When i call this API by "curl" this is the mistake:
<am:fault xmlns:am="http://wso2.org/apimanager">
<am:code>404</am:code>
<am:type>Status report</am:type>
<am:message>Not Found</am:message>
<am:description>
The requested resource (/test/1/ping) is not available.
</am:description>
When I see carbon at "C" or "D" (Main > Metadata > List > APis) the API is there. I dont know why this mistake.
Did you setup deployment synchronizer? see SVN-Based Deployment Synchronizer for Carbon 4.2.0-Based Products .
When you publish an api from the publisher, it creates relevant synapse configurations to handle request related to this api in the manager node (see AM_HOME/repository/deployment/server/synapse-configs/default/api in the manager node and you would find a xml with the api name.) . Since gateway worker nodes handle requests, these files should be in the worker nodes. deployment synchronizer is used to move this configurations to the worker nodes automatically. You can do this manually by copying content in synapse-configs folder in the manager node to all the worker nodes if you do not want a svn base synchronizer

how to get notice that one key has been created in redis

I have a outer service which will insert data to redis(I can get the keys of the data),but this may take some times , so the question is, how can I get to know that the data is comming.I want to show that in a page based django??
Use PUB/SUB of redis.
When your other service inserts new data, publish key on some channel...
So your django subscribes on channel "datachanged"
./redis-cli subscribe "datachanged"
And your service send event over channel
./redis-cli set "key:abc123" "some value"
./redis-cli publish "datachanged" "key:abc123"
Also you can use "Redis Keyspace Notifications" if your redis is newer then 2.8.0 (http://redis.io/topics/notifications)

Truncated Java object when passing through JAX-WS WebService

I am currently working on a project that uses JAX-WS webservices in Java.
The global topic is this : the user creates locally an object, let's say an Agent. He calls a first webservice and passes its Agent to the webservice. The webservice treats the Agent (modifies its properties : e.g. lifepoints), and passes it to another webservice. This call is made from the first webservice, so the user has nothing to do in the process.
After a chain of several webservices, the user retrieves the Agent that has been modified.
The aim of my project is to design 2 parts:
a framework that specifies the behaviour previously described : webservices, Agents and the process of migration
a demo application using my framework. The main difference is the addition of a GUI and a new class Avatar, that extends Agent. So the migration process is still being done "by the framework", with Agent objects.
The following code shows a simple example of how I call my webservice, host my Avatar, then retrieves the agent from the service :
// connection to the server
URL endpoint= new URL("http://SERVER/tomcat/KiwiBidonDynamique/ServiceWebBidonDeDadou?wsdl");
QName serviceName=new QName("http://avatar/","ServeurKiwiBidonService");
Service service = Service.create(endpoint, serviceName);
WebService port = service.getPort(WebService.class);
Avatar myAvatar = new Avatar(1, "Jack the Ripper");
port.hostAgent(myAvatar);
// some process on the service...
Avatar myAvatarTransformed = (Avatar) port.getAgent("AgentNumberOne");
When I do that, I get an exception on the final line :
Exception in thread "main" java.lang.ClassCastException: agent.Agent cannot be cast to avatar.Avatar
After a lot of log reading, I guess the reason is the way the webservice works. When being called, my Avatar given in parameter is marshalled in my JVM then unmarshalled on the service, but the service only constructs an Agent when it unmarshalles. Doing so, it truncates the data specific to the Avatar. Then when I try to retrieve my Agent from the service, it cannot be cast to an Avatar.
Is there a way to keep the Avatar information while processing as an Agent on the service ?
Can I write my own marshalling/unmarshalling somehow ?
Thanks a lot.
If your webservice has Agent element defined as incoming data, then no it is not possible to unmarshall it into an inherited class. I guess it would be possible to write your own marshaller but it is not as easy as it sounds (I would advise against it). Either write a separate WS for each class (messy) or make the incoming data have an element that can store additional structures, like type:any (also messy). The truth is WS are not exactly OO.

How to unpublish a web service using JAX-WS aadn bind to a different address

I've a JAX-WS web service deployed into an embedded Jetty server
I need to change the IP address which is associated with the Endpoint
In order to publish I do:
Service service = new Service();
Endpoint.publish(address, service);
What happen is that when i stop and restart the server, the Service is published again and bind to the new address I provide, but I get a Warning like this:
WARNING: "GMBAL901: JMX exception on registration of MBean MBeanImpl[type=WSEndpoint,name=MyServiceService-myservice_servicePort,oname=com.sun.metro:pp=/,type=WSEndpoint,name=MyServiceService-myservice_servicePort]"
and if I query both old address (e.g. 127.0.0.1) and new one (e.g. 192.168.X.X) both are still answering (with two different instances of myService.
I wouldn't have this behavior, I want that the WS is unbound from the old address.
How can I do?
Find out that I simply need to create the EndpointObject, publish it, and when I need to restart that will be enough to stop ep (it will ensure that same ep will not be republished), than creating a new one and republish it.
Endpoint ep;
...
if (ep != null && ep.isPublished()){
ep.stop();
}
ep = Endpoint.create(service);
ep.publish(getEndpointAddress(port, service));
till is better to wait half a second before restarting the server where the WS is published as sometime it stuck