Jean-Sebastien Delfino wrote:
Samisa Abeysinghe wrote:
Jean-Sebastien Delfino wrote:
Hi,

I'm using the REST support in Axis2C 0.93 to invoke SCA services in Apache Tuscany, and it has been working pretty well so far. I now would like to customize a little how requests get dispatched to a particular service.

I am currently using the following URL: http://localhost:9090/axis2/services/customer?id=1234 to invoke my customer info Web service and pass to it customer id 1234, so far so good.

Now I would like to change this a little and invoke the customer info service using a slightly different URL: http://localhost:9090/axis2/services/customer/1234. Customer id 1234 is now specified as part of the path instead of a parameter. I still need a single service for all customers, and the ability to get the customer id in the Axis2 service skeleton.

Is this possible?
This is not possible as of now, as we are dependent on the '?' separation for parameters.
What do I need to put in my services.xml to enable this? and how will I get the part of the URL after customer/ in my Axis2 service skeleton?
Unfortunately we have not implemented a mechanism for this. In theory, you should be able to write your own dispatcher to get this done. e.g. see modules/core/engine/req_uri_disp.c. You write a custom dispatcher and include that extended dispatcher in "<phaseOrder type="inflow">" section's 'Dispatch' phase in axis2.xml. However we have not tested plugging in dispatchers. Alternatively, you can extend the logic in axis2_req_uri_disp_find_op method of modules/core/engine/req_uri_disp.c. and get the rest of the string after customer/ in the URI and set this as a property in the message context. Then, in the service skeleton, you can pull this property from the message context. I think this approach is simpler than to try and write a custom dispatcher.

Thanks,
Samisa...


Thanks...



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


Hi,

Thanks for the info. I am now able to plug in a custom dispatcher. I prefer this approach as I want Tuscany to work with a plain Axis2C distribution without having to customize its source.

I had to add the following to my axis2.xml:
   <dispatchOrder>
       <dispatcher class="tuscany_sca_ws_dispatcher"/>
   </dispatchOrder>

Adding to the <phaseOrder type="inflow"> section didn't seem to trigger the loading of my dispatcher.

I also had to make two minor code changes in Axis2C:

axis2c-src-0.93/modules/core/deployment/conf_builder.c
439a440,450
>         if(disp_node)
>         {
>             disp_element = AXIOM_NODE_GET_DATA_ELEMENT(disp_node,
>                 env);
>         }
>         if(!disp_element)
>         {
> qname_itr_has_next = AXIOM_CHILDREN_QNAME_ITERATOR_HAS_NEXT(disps,
>                 env);
>             continue;
>         }

This fixes a memory violation with disp_element not being initialized.

and in axis2c-src-0.93/modules/core/description/handler_desc.c
290,291c296
< if (AXIS2_PARAM_CONTAINER_IS_PARAM_LOCKED(handler_desc_impl->parent, env,
<         AXIS2_PARAM_GET_NAME(param, env)) )
---
>     if (handler_desc_impl->parent)
293,295c298,304
< AXIS2_ERROR_SET(env->error,AXIS2_ERROR_PARAMETER_LOCKED_CANNOT_OVERRIDE,
<             AXIS2_FAILURE);
<         return AXIS2_FAILURE;
---
> if (AXIS2_PARAM_CONTAINER_IS_PARAM_LOCKED(handler_desc_impl->parent, env,
>             AXIS2_PARAM_GET_NAME(param, env)) )
>         {
> AXIS2_ERROR_SET(env->error,AXIS2_ERROR_PARAMETER_LOCKED_CANNOT_OVERRIDE,
>                 AXIS2_FAILURE);
>             return AXIS2_FAILURE;
>         }

Ths is to avoid a memory violation because the parent of my custom dispatcher's handler_desc is NULL. I am not sure how to set it, or if the Axis2C runtime should set the parent after the handler is loaded.

I hope this makes sense as I've been guessing what to do by stepping into the code in the debugger... But I am able to get my dispatcher invoked at least when the other dispatchers play along and execute successfully.

Now my next question is: How can I control the order of execution of the dispatchers? Currently the engine's req_uri_disp dispatcher always seems to be invoked first and fails if it doesn't find the target service in the service configuration, so my dispatcher doesn't get a chance to be called. This pretty much defeats the purpose as my dispatcher is supposed to contribute new dispatching logic :) unless I'm missing something...

Thanks,


I have spent more time investigating this so I thought I'd give an update on where I am with my attempt to plug in a custom dispatcher:

SOAP Web Services:
- I am able to register a module and a handler in the Dispatch phase, get it loaded and invoked and handle the dispatching as needed in my environment. - The only problem I have left with this approach is that properties set by my handler in the message context are not passed to the service skeleton at all. From what I can see, the message context passed to a service skeleton is different from the message context passed to a handler in the Dispatch phase (looks like the engine is creating a new "out" message context from the original message context without carrying over any of the properties).

REST Web Services:
- The handler registered in the Dispatch phase by my module is not invoked at all. - A custom dispatcher registered using <dispatchOrder> and the two changes/fixes I described in my previous email gets invoked, but only after req_uri_disp so it does not allow me to effectively alter/participate in the dispatching logic.

For REST Web Services I am left for now with an ugly hack... write a custom HTTP server main and there patch the "ops" pointer to the invoke function of req_uri_disp (like if I was patching a vtable in memory in C++, it's really an ugly hack). Here's the code I added after line 155 of http_server_main.c to do this:

   // Get my hands on the conf_ctx and the Axis2 conf
axis2_http_server_impl_t* server_impl = ((axis2_http_server_impl_t *)(server));
  axis2_conf_ctx_t* conf_ctx = server_impl->conf_ctx;
  axis2_conf_t* conf = AXIS2_CONF_CTX_GET_CONF(conf_ctx, env);
// Get the Dispatch phase axis2_array_list_t* phases = AXIS2_CONF_GET_IN_PHASES_UPTO_AND_INCLUDING_POST_DISPATCH(conf, env); axis2_phase_t* dispatch = (axis2_phase_t*)AXIS2_ARRAY_LIST_GET(phases, env, 2); // Get the req_uri_disp handler axis2_array_list_t* handlers = AXIS2_PHASE_GET_ALL_HANDLERS(dispatch, env); axis2_handler_t* disp_handler = (axis2_handler_t*)AXIS2_ARRAY_LIST_GET(handlers, env, 1); // Patch its invoke method and install mine.....
  disp_handler->ops->invoke = Axis2Dispatcher_invoke;
This hack got me to a point where I could at least test my Tuscany code but I seriously can't continue with such a hack and need a cleaner solution for this.

Do you have any creative idea on how to get a handler to participate in the Dispatch phase for REST services as well, like it works for SOAP Web Services? Now I've spent enough time stepping through the Axis2C code maybe I can even help debug this :) but I'd need a few pointers to where to look and an idea of the right / intended design for this and why the dispatching logic is different in the REST case...

Thanks,

--
Jean-Sebastien


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to