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]