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