Hi, Sreekant:
You did a good job for our common problems, Sreekant!
I anticipated you would cover it, and you did covering.
Thanks a lot!!
The current version of "our collaborated solution"
would be enough to follow the spec. If you hope that
you would like immediately to start implementations of
the jax-rpc handlers, it'll be the easiest way.
However, if a moment's delay is acceptable to you,
I'd like to propose the other way which is more elegant
approaches to handle the jax-rpc scenario.
As you know, the architecture of jax-rpc handler gives
very high level adaptability and portability to users.
In addition in the AXIS implementations, if we want to
configure (i.e. add and/or remove handler components,
or change the order), we have to do is just one thing;
editing "*.wsdd" (and re-deploy it).
OTOH, your posted implementation has a risk to reduce
the advantages for the jax-rpc handler users, therefore,
I'd like to recommend the following approach.
***** The rule of the new flow definition *****
.........*.........*.........*.........*.........*.........*
a)I define a special parameter for "*.wsdd" to setting up
a user specific response flow in case of return "false".
b)The parameter's name is "OnReturnFalseRestartAt".
c)It can *optionally* appear under the "<handlerInfoChain>"
as the child node of the "<handlerInfo>".
d)The appropriate value is an integer value (-1, 0, 1, 2..)
to indicate the starting point index of response flow.
(Exceptionally, the "-1" indicates the runtime doesn't
invoke any handleResponse methods and directly sends back
the response message from handleRequest to the client.)
.........*.........*.........*.........*.........*.........*
***** A sample definition of deploy.wsdd *****
(--- How to use "OnReturnFalseRestartAt" parameter ---)
----- <CUT> ----- <CUT> ----- <CUT> ----- <CUT> ----- <CUT> -----
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<service name="testWebService" provider="java:RPC">
<parameter name="className" value="webservices.testWebService"/>
<parameter name="allowedMethods" value="*"/>
<handlerInfoChain>
<handlerInfo classname="samples.jaxrpc.hello.ServerHandlerA">
<parameter name="OnReturnFalseRestartAt" value="0"/>
</handlerInfo>
<handlerInfo classname="samples.jaxrpc.hello.ServerHandlerB">
<parameter name="OnReturnFalseRestartAt" value="-1"/>
</handlerInfo>
</handlerInfoChain>
</service>
</deployment>
----- <CUT> ----- <CUT> ----- <CUT> ----- <CUT> ----- <CUT> -----
***** Patch for HandlerChainImpl.java *****
----- <CUT> ----- <CUT> ----- <CUT> ----- <CUT> ----- <CUT> -----
// added by Toshi <[EMAIL PROTECTED]>
private int falseIndex;
public boolean handleRequest(MessageContext _context) {
SOAPMessageContext context = (SOAPMessageContext) _context;
// boolean processFault = false; === no use ===
// added by Toshi <[EMAIL PROTECTED]>
falseIndex = -1;
for (int i = 0; i < size(); i++) {
Handler currentHandler = getHandlerInstance(i);
try {
if (currentHandler.handleRequest(context) == false) {
// added by Toshi <[EMAIL PROTECTED]>
falseIndex = i;
return false;
}
} catch (SOAPFaultException sfe) {
throw sfe;
}
}
return true;
}
public boolean handleResponse(MessageContext context) {
// added by Toshi <[EMAIL PROTECTED]>
int endIdx = handlerInfos.size() - 1;
if (falseIndex != -1) {
HandlerInfo info = (HandlerInfo)
this.handlerInfos.get(falseIndex);
String st = (String)
info.getHandlerConfig().get("OnReturnFalseRestartAt");
if (st != null) {
endIdx = Integer.parseInt(st);
} else {
endIdx = falseIndex;
}
}
// for (int i = size() - 1; i >= 0; i--) === Comented out ===
// changed by Toshi <[EMAIL PROTECTED]>
for (int i = endIdx; i >= 0; i--)
if (getHandlerInstance(i).handleResponse(context) == false)
return false;
return true;
}
----- <CUT> ----- <CUT> ----- <CUT> ----- <CUT> ----- <CUT> -----
P.S.
Please call me by my nickname; "Toshi" which comes from
my given name "Toshiyuki".
Best Regards,
Toshi (Toshiyuki Kimura) <[EMAIL PROTECTED]>
R&D Headquarters
NTT DATA Corporation
-----Original Message-----
From: Sreekant Thirunagari [mailto:[EMAIL PROTECTED]
Sent: Friday, February 28, 2003 3:23 AM
To: [EMAIL PROTECTED]
Subject: Re: Handler chain implementation
Hi Toshiyuki Kimura,
Here are my suggestions.. follow the --->>
(1): H2(req) generates a response msg and the runtime
directly sends back it to the client
*** Currently, I'm not sure this path is needed ***
--->> According to spec the handler that intends to return false is
responsible
to set the response message in handleRequest method. but i don't see any
need
or how to do this. Even i am not sure if we need to handle this.
(2): H1(res) generates a response msg, and after that
the runtime sends back it to the client
--->> I want to address (2) and (4) together.
(3): H2(res) generates a response msg, and the runtime
invokes the next handler ( handleResponse of H1 )
*** The spec says "It should be the default". ***
---->> So the runtime system should be able to make a decesion to follow
'default' or look for user customization??
I think this can be achieved by setting a property in context
passed
to the handler that intends to return false.
(4): H3(res) generates a response msg, and the runtime
invokes the next handler ( handleResponse of H2 )
----->> As we ruled out (1) .. atleast for now and we know what default
means..
i want to bring up the question i raised last time .. what are the
customizations user should be allowed to do??? I think two options mentioned
below would be more generic.
(a) As in the solution you proposed just let system invoke all the
handlers leave the responsibility to user implementation of handleResponse.
Option (4)
set empty string as "HandlerFault" property in context passed to the
handler .. to indicate the ChainImpl to invoke all the handlers and the
handleResponse implementations of configured handlers are responsible for
how
they generate response and pass it over. (This is a convention i came up
with ..
obviously there should a better way of conveying this)
(b) Should be able to say to the system to start from a perticular
point
in the chain and continue from there. If he configures it to be H1 that
would be
the only handler invoked and responsible for setting appropriate response
SOAP
message.
set class name of the handler in configured chain from which you
want to
start as "HandlerFault" propert y in context passed to the handler
So now we can mix both our solutions to achieve more generic solution.
It
doesn't look readable but i tried my best
Introduced '--->>' for parts to be noted. I used the same code u sent in
prevous
mails and changed it a bit.
--------- Handler -----------------
public boolean handleRequest(
javax.xml.rpc.handler.MessageContext context) {
// **** if you want to return false ****:
// set the class name of the handler implementation:
--->>> //context.setProperty("HandlerFault", this.getClass().getName());
String handlefault = ""; // to invoke all the handlers in chain
context.setProperty("HandlerFault", handlefault);
or
String handlefault = "MyHandlers.handler3" // to start from handler -3
class
in chain
//Note that this should be an existing handler in configured chain.
context.setProperty("HandlerFault", handlefault);
or
-- DON'T SET THIS PROPERTY TO ALLOW THE SYSTEM TO FOLLOW DEFAULT
FLOW ---
return false;
}
public boolean handleResponse( javax.xml.rpc.handler.MessageContext
context) {
// get the state (class name was set or not) from MsgCtx:
String name = (String)context.getProperty("HandlerFault");
//if (name != null && name instanceof String &&
name.equals(this.getClass().getName())) {
---->> if (name != null && name instanceof String ) {
if(name.equals(""){
// this is a fault situation and is upto you how to
handle
it...
}
else if(name.equals(this.getClass().getName())){
// this is a fault situation and you are responsible to
set
SOAP response message
}
} else {
:
:
}
return true;
}
------------------HandlerChainImpl -----------------------------------------
protected int lastHandlerIndex = 0;
public boolean handleRequest(MessageContext _context) {
SOAPMessageContext context = (SOAPMessageContext) _context;
boolean processFault = false;
for (int i = 0; i < size(); i++) {
Handler currentHandler = getHandlerInstance(i);
lastHandlerIndex = i;
try {
if (currentHandler.handleRequest(context) == false) {
// get the state (class name was set or not) from MsgCtx:
String name =
(String)context.getProperty("HandlerFault");
boolean classFound = false;
if( (name != null) && name instanceof String ) {
if(name.equals("")){
lastHandlerIndex = size() -1;
}
else if( ! name.equals("")){
// have to traverse back from this handler class
that is set by user ..
for (int j = 0; j < size(); j++) {
if(
name.equals(getHandlerInstance(j).getClass().getName())) {
// found it ..
classFound = true;
lastHandlerIndex = j; // set this as the
index to start.
continue;
}
}// end find class for
if(!classFound){
// automatically falls back to default.. in
case
of wrong class being set
// or we can think of throwing a runtime
exception here...
}
}// end of if name != ""
}
return false;
}
} catch (SOAPFaultException sfe) {
throw sfe;
}
}
}
public boolean handleResponse(MessageContext context) {
for (int i = lastHandlerIndex; i >= 0; i--){
Handler currentHandler = getHandlerInstance(i);
if (getHandlerInstance(i).handleResponse(context) == false)
return false;
}
return true;
}
-----------------------------------------------
These chages along with the one u mentoined SOAPService class should
take
care of everything.
Regards,
Sreekant