This will not serve as a comprehensive tutorial in developing services and clients for Axis2/C, but rather intended to provide some help for starters.
Apache Axis2/C is an engine for web services developed in C – there’s another implementation in Java. You can find an illustration of SOA here.
You first need to download and install Apache Axis2/C 1.3.0. You can download the binaries or sources from the Apache Axis2/C website. It would be easier to install the binaries if you are a beginner.
So let’s get started with developing a service. We’ll create a service to sort a set of integers in ascending or descending order.
Service
The service should have two functions:
- axis2_get_instant – creates the service skeleton
- axis2_remove_instant – removes the instant
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | AXIS2_EXPORT int axis2_get_instance(axis2_svc_skeleton_t **inst, const axutil_env_t *env) { *inst = axis2_sort_create(env); if (!(*inst)) return AXIS2_FAILURE; return AXIS2_SUCCESS; } AXIS2_EXPORT int axis2_remove_instance(axis2_svc_skeleton_t *inst, const axutil_env_t *env) { if (inst) return AXIS2_SVC_SKELETON_FREE(inst, env); return AXIS2_FAILURE; } /* Create the service skeleton */ axis2_svc_skeleton_t * axis2_sort_create(const axutil_env_t *env) { axis2_svc_skeleton_t *svc_skeleton = NULL; svc_skeleton = AXIS2_MALLOC(env->allocator, sizeof(axis2_svc_skeleton_t)); svc_skeleton->ops = &sort_svc_skeleton_ops_var; svc_skeleton->func_array = NULL; return svc_skeleton; } |
axis2_get_instant should create axis2_svc_skeleton struct with corresponding functions assigned. These functions are
- init – initializes the skeleton
- invoke – invokes the service
- on_fault – this is called when an fault is detected
- free – frees the skeleton instant
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | /* Functions for axis2_svc_skeleton */ int AXIS2_CALL sort_free(axis2_svc_skeleton_t *svc_skeleton, const axutil_env_t *env); axiom_node_t* AXIS2_CALL sort_invoke(axis2_svc_skeleton_t *svc_skeleton, const axutil_env_t *env, axiom_node_t *node, axis2_msg_ctx_t *msg_ctx); int AXIS2_CALL sort_init(axis2_svc_skeleton_t *svc_skeleton, const axutil_env_t *env); axiom_node_t* AXIS2_CALL sort_on_fault(axis2_svc_skeleton_t *svc_skeli, const axutil_env_t *env, axiom_node_t *node); /* Skeleton */ static const axis2_svc_skeleton_ops_t sort_svc_skeleton_ops_var = { sort_init, sort_invoke, sort_on_fault, sort_free }; |
Now comes the main part of the service – implementation of the invoke function.
This function will be called with a reference to request. The XML request will be passed as a axiom_node_t, and you can navigate through it easily using functions axiom_node_get_first_child and axiom_node_get_next_sibling.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | /* Process the request */ axiom_node_t* AXIS2_CALL sort_invoke(axis2_svc_skeleton_t *svc_skeleton, const axutil_env_t *env, axiom_node_t *node, axis2_msg_ctx_t *msg_ctx) { return axis2_sort(env, node); } /* Process the request */ axiom_node_t * axis2_sort(const axutil_env_t *env, axiom_node_t *node) { AXIS2_ENV_CHECK(env, NULL); if(!node) return sort_error(env); axiom_node_t *order_node = axiom_node_get_first_child(node, env); axis2_char_t *order_str = get_string(order_node, env); if(!order_str) return sort_error(env); axiom_node_t *list = axiom_node_get_next_sibling(order_node, env); if(!list) return sort_error(env); axiom_node_t* current = axiom_node_get_first_child(list, env); if(!current) return sort_error(env); int i; a = AXIS2_MALLOC(env->allocator, sizeof(long int) * MAX); for(i = 0; i < MAX && current; i++) { axis2_char_t *str = get_string(current, env); a[i] = strtol(str, NULL, 10); current = axiom_node_get_next_sibling(current, env); } int N = i; if(axutil_strcmp(order_str, "asc")) return build_sort_response(env, N, 1); else if(axutil_strcmp(order_str, "des")) return build_sort_response(env, N, -1); else return sort_error(env); } |
After parsing the input you should calculate and prepare the response of the service.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | /* Generate the response */ axiom_node_t * build_sort_response(const axutil_env_t *env, int N, int order) { axis2_char_t value_str[255]; axiom_node_t *main_node; int i, j; for(i = 0; i < N; i++) for(j = 1; j < N; j++) if((a[j] - a[j-1]) * order > 0) { long int temp = a[j]; a[j] = a[j-1]; a[j-1] = temp; } axiom_namespace_t *ns1 = axiom_namespace_create(env, "http://axis2/test/sort", "ns1"); axiom_element_create(env, NULL, "result", ns1, &main_node); for(i = 0 ; i < N; i++) { axiom_node_t *value_node; sprintf(value_str, "%ld", a[i]); axiom_element_t *value_ele = axiom_element_create(env, main_node, "value", NULL, &value_node); axiom_element_set_text(value_ele, env, value_str, value_node); } AXIS2_FREE(env->allocator, a); return main_node; } |
That’s it now we have created the service, but we need to create the service descriptor services.xml
1 2 3 4 5 | <service name="sort"> <parameter name="ServiceClass" locked="xsd:false">sort</parameter> <description>Sort service example.</description> <operation name="sort"/> </service> |
Here’s the code of the service: sort_service.c and the descriptor: services.xml.
Then compile the service using gcc
gcc -shared -olibsort.so -I$AXIS2C_HOME/include/axis2-1.3.0/ -L$AXIS2C_HOME/lib -laxutil -laxis2_axiom -laxis2_parser -laxis2_engine -lpthread -laxis2_http_sender -laxis2_http_receiver sort_service.c
The environment variable AXIS2C_HOME should be set to the axis2 installation folder.
Copy libsort.so and services.xml to folder AXIS2C_HOME/services/sort/.
Now start the axis server or restart if it’s already running, buy executing axis2_http_server. And check if the service is correctly deployed by checking http://localhost:9090/axis2/services.
Now that the service is running fine we can start creating the client.
Client
First we should set the properties and create the svc client
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | const axis2_char_t *client_home = NULL; axis2_svc_client_t* svc_client = NULL; axiom_node_t *payload = NULL; axiom_node_t *ret_node = NULL; /* Create environment */ axutil_env_t *env = axutil_env_create_all("sort_client.log", AXIS2_LOG_LEVEL_TRACE); /* Location of the service */ axis2_char_t *address = "http://localhost:9090/axis2/services/sort"; printf("Using address : %s\n", address); /* Creating options */ axis2_options_t *options = axis2_options_create(env); axis2_endpoint_ref_t* endpoint_ref = axis2_endpoint_ref_create(env, address); axis2_options_set_to(options, env, endpoint_ref); /* Creating svc client */ client_home = AXIS2_GETENV("AXIS2C_HOME"); if (!client_home && !strcmp(client_home, "")) { printf("AXIS2C_HOME not set\n"); return -1; } svc_client = axis2_svc_client_create(env, client_home); if (!svc_client) { printf("Error creating service client\n"); AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Stub invoke FAILED: Error code:" " %d :: %s", env->error->error_number, AXIS2_ERROR_GET_MESSAGE(env->error)); return -1; } axis2_svc_client_set_options(svc_client, env, options); |
Then build the request.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | axiom_node_t * build_om_request(const axutil_env_t *env) { axiom_node_t *main_node; axiom_node_t *order_node; axiom_node_t *values_node; axis2_char_t value_str[255]; int i; axiom_namespace_t *ns1 = axiom_namespace_create(env, "http://axis2/test/sort", "ns1"); axiom_element_create(env, NULL, "sort", ns1, &main_node); axiom_element_t *order_ele = axiom_element_create(env, main_node, "order", NULL, &order_node); axiom_element_set_text(order_ele, env, "des", order_node); axiom_element_t *values_ele = axiom_element_create(env, main_node, "values", NULL, &values_node); int N = 20; for(i = 0 ; i < N; i++) { axiom_node_t *value_node; sprintf(value_str, "%ld", i + 100); axiom_element_t *value_ele = axiom_element_create(env, values_node, "value", NULL, &value_node); axiom_element_set_text(value_ele, env, value_str, value_node); } return main_node; } |
Send the request.
1 | ret_node = axis2_svc_client_send_receive(svc_client, env, payload); |
Here’s the code of the service: sort_client.c. Now compile the client.
gcc -o sort_client -I$AXIS2C_HOME/include/axis2-1.3.0/ -L$AXIS2C_HOME/lib -laxutil -laxis2_axiom -laxis2_parser -laxis2_engine -lpthread -laxis2_http_sender -laxis2_http_receiver sort_client.c -ldl -Wl,--rpath -Wl,$AXIS2C_HOME/lib
Run it
Run the client to see what happens.
What happens if the client sends an empty request?


Recent Comments