Index: developerguide.html =================================================================== --- developerguide.html (revision 437531) +++ developerguide.html (working copy) @@ -3,15 +3,15 @@ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+Please send your feedback to developer mailing list: axis-c-dev@ws.apache.org (Please remember to prefix the subject with [Axis2]). To subscribe to developer @@ -25,7 +25,7 @@
Operations associated with a struct are bundled into an operations struct, -and the operations struct is exposed in the header file. The real -implementation struct with the data fields is hidden from the user, and lives -in the source file. To ease the user from using the complex syntax required -by the use of the operations struct, macros are provided to access the -functions associated with a given struct. Since the data is hidden, it is the -usual practice to provide getter and setter methods for the data fields of -the struct, in addition to the other processing functionality. Actual -function implementations are mapped to the functions in the operations struct -in the source file by means of function pointer assignments.
+Operations associated with a struct are bundled into an operations struct +('ops' struct), and this ops struct is exposed in the header file. The real +implementation struct ('impl' struct) with the data fields is hidden from the +user, and lives in the source file. To ease the user from the complex syntax +required to access the functions in a given ops struct, macros are provided +to access them. Since the data is hidden, it is the usual practice to provide +getter and setter methods for the data fields of the struct, in addition to +the other processing functionality. The actual function implementations in +the source file are mapped to the ops struct functions declared in the header +file, by means of function pointer assignments.
-Here is a sample header file associated with the "foo" struct.
+Here is a sample header file associated with the "foo" struct. (Imagine a +class called "foo" in the proper object oriented programming model.)
/* axis2_ foo.h */typedef struct axis2_foo_ops axis2_foo_ops_t; @@ -69,13 +70,15 @@ axis2_foo_t * axis2_foo_create(const axis2_env_t *env); -/* Macros are provided to access functions defined in the ops (operations structure)*/ +/* Macros are provided to access functions defined in the ops structure */ -#define AXIS2_FOO_BAR(foo, data)\ - ((foo)->ops->bar(data)) +#define AXIS2_FOO_BAR(foo, env, data)\ + ((foo)->ops->bar(foo, env, data)) #define AXIS2_FOO_FREE(foo, env)\ - ((for)->ops->free(env, foo))+ ((foo)->ops->free(foo, env)) + +
The implementation file for "foo" struct is shown below.
/* foo.c */
#include <axis2_foo.h>
@@ -88,31 +91,33 @@
my_type my_data; /*private data*/
};
+
/* Function Headers */
-void AXIS2_CALL axis2_foo_bar(void *data);
-axis2_status_t AXIS2_CALL axis2_foo_free(const axis2_env_t *env, axis2_foo_t *foo);
+void AXIS2_CALL axis2_foo_bar(axis2_foo_t *foo, const axis2_env_t *env, void *data);
+axis2_status_t AXIS2_CALL axis2_foo_free(axis2_foo_t *foo, const axis2_env_t *env);
-/* Function Implementation */
+/* Function Implementations */
axis2_foo_t * AXIS2_CALL axis2_foo_create(const axis2_env_t *env)
{
axis2_foo_impl_t * foo_impl = NULL;
- /* create axis2_foo_t and initialize private data */
+ /* create axis2_foo_impl_t structure and initialize private data */
/* create ops structure of foo */
/* bind ops to functions */
foo_impl->foo.ops->bar = axis2_foo_bar;
foo_impl->foo.ops->free = axis2_foo_free;
+
return &(foo_impl->foo);
}
-void AXIS2_CALL axis2_foo_bar(void *data)
+void AXIS2_CALL axis2_foo_bar(axis2_foo_t *foo, const axis2_env_t *env, void *data)
{
/* do something */
}
-axis2_status_t AXIS2_CALL axis2_foo_free(const axis2_env_t *env, axis2_foo_t *foo)
+axis2_status_t AXIS2_CALL axis2_foo_free(axis2_foo_t *foo, const axis2_env_t *env)
{
/* do the dirty work of cleaning the allocated memory */
}
@@ -120,22 +125,24 @@
If you had a closer look into the given sample above, you will see that almost all functions take a double pointer to the axis2_env struct. To learn -more on environment used in Axis2/C, please have a look into the architecture notes.
When writing services, as well as client programs, you have to ensure that -you do proper memory management. You need to be aware of the parts of the -memory you have allocated to deallocate in order to avoid memory leaks (and -to avoid those nasty segmentation faults ;-) ).
+When writing services as well as client programs, you have to ensure that +you do proper memory management. You need to be careful to deallocate the +memory you have allocated in order to avoid memory leaks (and to avoid those +nasty segmentation faults ;-) ). Remebering where you allocate memory is a +good practice, which will help you to properly free such allocated memory.
To understand, how the allocated memory is reclaimed, it is worth looking +
To understand how the allocated memory is reclaimed, it is worth looking at the service skeleton interface which is defined in axis2_svc_skeleton.h
-AXIS2_DECLARE_DATA struct axis2_svc_skeleton_ops +-+AXIS2_DECLARE_DATA struct axis2_svc_skeleton_ops { int (AXIS2_CALL * free)(axis2_svc_skeleton_t *svc_skeli, const axis2_env_t *env); ... @@ -147,20 +154,28 @@ axis2_array_list_t *func_array; };-The service skeleton implementation should implement the free function and -attach that to the operations struct of axis2_svc_skeleton_t struct. This -free function is called each time after web services request is served.
+ +The service skeleton implementation should implement the
+free+function and attach that to the ops struct of +axis2_svc_skeleton_tstruct. Thisfreefunction is +called each time after a web services request is served.Let's try to understand this through an example.
+ +Example: Service skeleton implementation for math service.
-The following code shows the implementation of math_free function which is -to be attached to the ops of axis2_svc_skeleton_t struct. Usually the memory -allocated for operations struct, function array and service skeleton struct -are cleaned in this. You may clean additional memory here if you have -allocated any specific memory blocks in math_create function or elsewhere -depending on your implementation specifics.
+The following code shows the implementation of
+ +math_free+function which is to be attached to the ops of +axis2_svc_skeleton_tstruct. Usually the memory allocated for +the operations struct, the function array and the service skeleton struct are +cleaned inside this. You may clean additional memory here if you have +allocated any specific memory blocks inmath_createfunction or +elsewhere, depending on your implementation specifics.int AXIS2_CALL math_free(axis2_svc_skeleton_t *svc_skeleton, const axis2_env_t *env) { if(svc_skeleton->ops) @@ -181,10 +196,14 @@ return AXIS2_SUCCESS; }-In the axis2_math_create function you assign the function pointer of -math_free function to the free function of the operations struct. As you can -see, now the SOAP engine has a function reference to perform garbage -collection after each service request.
+ + +In the
+ +axis2_math_createfunction, you assign the function +pointer ofmath_freefunction to thefreefunction +of the operations struct. As you can see, now the SOAP engine has a function +reference to perform garbage collection after each service request.AXIS2_EXTERN axis2_svc_skeleton_t * AXIS2_CALL axis2_math_create(const axis2_env_t *env) { axis2_svc_skeleton_t *svc_skeleton = NULL; @@ -192,33 +211,36 @@ svc_skeleton->ops = AXIS2_MALLOC(env->allocator, sizeof(axis2_svc_skeleton_ops_t)); - svc_skeleton->ops->free = math_free; ... return svc_skeleton; -}+} +
SOAP engine frees the memory allocated for the axiom_node_t struct that -is used to from the response SOAP message. However, it is the responsibility -of the service developer to clean any additional memory allocated.
+SOAP engine frees the memory allocated for the axiom_node_t
+struct that is used to form the response SOAP message. However, it is the
+responsibility of the service developer to clean any additional memory
+allocated.
Coding conventions used with the Axis2 project is listed in this document.
-CuTest library is used to write unit tests in Axis2/C.
@@ -227,23 +249,28 @@2. Add the module's test suite to the main unit test suite.
+ +This section illustrates how to add a unit test case to the util module. -Let's take for example the unit tests for axis2 stream. There are two files +Let's take, for example, the unit tests for axis2 stream. There are two files named util_stream_test.c/.h placed into modules/util/test folder. Here's a -sample code written to test the operation axis2_stream_ops_read.
-#include "util_stream_test.h" +sample code written to test the operation +axis2_stream_ops_read. ++#include "util_stream_test.h" void Testaxis2_stream_ops_read(CuTest *tc) { char actual[10]; axis2_allocator_t *allocator = axis2_allocator_init(NULL); - axis2_env_t *env = axis2_environment_create(allocator,NULL, NULL, NULL, NULL); + axis2_env_t *env = axis2_environment_create(allocator, NULL, NULL, NULL, NULL); axis2_stream_read(env->stream, actual, 10); char *expected = strdup("aaaaaaaaa"); CuAssertStrEquals(tc, expected, actual); -}+} +
The prototype of the function should be added to the header file. The test suite is defined in util_test.c. You need to add the above defined test case @@ -256,15 +283,17 @@ { CuSuite* suite = CuSuiteNew(); - SUITE_ADD_TEST(suite, Testaxis2_stream_ops_write); + SUITE_ADD_TEST(suite, Testaxis2_stream_ops_read); SUITE_ADD_TEST(suite, Testaxis2_log_ops_write); SUITE_ADD_TEST(suite, Testaxis2_hash_ops_get); + return suite; -} +} +
Now you need to add the Util module test suite to the main test suite.
+Now you need to add the util module test suite to the main test suite.
#include <CuTest.h>
#include "../../util/test/util_test.h"
#include "../../common/test/common_test.h"
@@ -286,44 +315,10 @@
{
RunAllTests();
return 0;
-}
+}
+
You can either run only the unit tests written for the util module or run all the tests.
- -For each module, system tests should be provided in -modules/test/<module folder>. For each system test you need to add a -new function and call it from the main method.
- -Example:
- -To test the AXIOM module, you need to create a file named test_om.c under the -directory modules/test/xml/om. A sample test_om.c might look like as -follows.
-#include <axiom_stax_builder.h>
-#include <axiom_document.h>
-#include <axiom_node.h>
-#include <axiom_element.h>
-#include <axiom_text.h>
-#include <axis2_xml_reader.h>
-
-int test_om_build()
-{
- axis2_xml_reader_t *reader = NULL;
- axiom_node_t *node1 = NULL ,*node2 = NULL ,*node3 = NULL;
- axiom_element_t *ele1=NULL,*ele2=NULL,*ele3 = NULL;
- axis2_stax_om_builder_t *builder = NULL;
- axiom_document_t *document = NULL;
-
- ...
-}
-
-int main(void)
-{
- test_om_build();
- test_om_serialize();
-}