Hi,
Some ideas that may possibly help.
Sorry in advance 'cause I don't know enough to give you a precise response.
Another idea to consider would be to add a simple web proxy (squid
maybe before your service in the network) and that could probably
handle the cache problem in a much more eficient manner and sidestep
this setup in your WebService.
A)
To get the output through CXF Interceptor :
To complete the cache you would still need to get the request...it is
in message object most probably...
I don't know enough to be able to add an InInterceptor that would stop
processing if request is cached and somehow send a response.
For simplicity you could add the request data from the InInterceptor
to some data structure of your own to grab it later on output
processing, although it seems your InInterceptor would complete the
request when it is known...
Possibly your endPoint could look at some datastructure that you setup
to see that response is cached and then do nothing.
public class FileLogOutInterceptor extends AbstractPhaseInterceptor<Message>{
static private final String LOG_SETUP =
FileLogOutInterceptor.class.getName() + ".log-setup";
public FileLogOutInterceptor() {
super(Phase.PRE_STREAM);
addBefore(LoggingOutInterceptor.class.getName());
}
public void handleMessage(Message message) throws Fault {
final OutputStream os = message.getContent(OutputStream.class);
String fileName="FileLog/Outbound";
if (os == null) {
log.error("Null OutputStream, cannot log to file="+fileName+",
returning");
return;
}
boolean hasLogged = message.containsKey(LOG_SETUP);
if (!hasLogged) {
message.put(LOG_SETUP, Boolean.TRUE);
final CacheAndWriteOutputStream newOut = new
CacheAndWriteOutputStream(os);
message.setContent(OutputStream.class, newOut);
newOut.registerCallback(new LoggingCallback(message,
os,fileName));
}
}
class LoggingCallback implements CachedOutputStreamCallback {
private final Message message;
private final OutputStream origStream;
private String fileName;
public LoggingCallback(final Message msg, final OutputStream
os, String fileName) {
this.message = msg;
this.origStream = os;
this.fileName=fileName;
}
public void onFlush(CachedOutputStream cos) { }
public void onClose(CachedOutputStream cos) {
StringBuilder builder = new StringBuilder();
try {
cos.writeCacheTo(builder);
fileName=DevUtils.writeFile(fileName,
".xml", builder.toString());
log.debug("Wrote debug file="+fileName);
} catch (IOException e) {
log.error("Could not write
file="+fileName+"
message="+e.getMessage()+" ignoring and allowing execution to
continue");
}
try {
//empty out the cache
cos.lockOutputStream();
cos.resetOut(null, false);
} catch (Exception ex) {
//ignore
log.error("Could not resetOut because
"+ex.getClass().getName()+"
message="+ex.getMessage());
}
message.setContent(OutputStream.class,
origStream);
}
}
}
B) To get the output through a JAXB ResponseHandler
I haven't set this up for SOAP, not sure that it can ...
public class MyResponseHandler implements ResponseHandler {
@Override
public Response handleResponse(Message message, OperationResourceInfo
operationResourceInfo,Response response) {
if( message==null || operationResourceInfo == null) return
response;
Exchange exchange = message.getExchange();
//Some application specific logic
List<MediaType> acceptContentTypes
=(List<MediaType>)exchange.get(Message.ACCEPT_CONTENT_TYPE);
boolean isJSON=false;
if(acceptContentTypes != null ) {
for(MediaType m : acceptContentTypes ) {
log.trace(m);
if("application/json".equalsIgnoreCase(m.toString())){
log.debug("Request is for JSON");
isJSON=true;
}
}
}
log.trace("isJSON="+isJSON);
OutputStream os = message.getContent(OutputStream.class);
message.setContent(OutputStream.class,new
WrappedOutputStream(os,isJSON,annotationMap));
return response;
}
class WrappedOutputStream extends OutputStream {
OutputStream wrapped;
StringBuilder buffer;
boolean isJSON;
Map<String,String> annotationMap;
WrappedOutputStream(OutputStream toWrap, boolean isJSON,
Map<String,String> annotationMap) {
if(toWrap==null) throw new NullPointerException("Cannot
wrap null
stream"); //No /dev/null for us
this.wrapped=toWrap;
this.isJSON=isJSON;
this.buffer=new StringBuilder();
this.annotationMap=annotationMap;
if(this.annotationMap==null)this.annotationMap=new
HashMap<String,String>();
}
public void write(int b) throws IOException {
//wrapped.write(b);
buffer.append((char)b);
}
public void flush() throws IOException {
//wrapped.flush();
}
public void close() throws IOException {
log.trace("Wrapped OutputStream close()");
wrapped.write(retVal.getBytes());
wrapped.flush();
wrapped.close();
}
}//class WrappedOutputStream
}//class MyResponseHandler
On Fri, Dec 2, 2011 at 10:10 AM, eswarup <[email protected]> wrote:
> Thanks Sergey..
>
> I had initially thought about CXF filters, but my concern is i'm looking for
> results after it's marshalled by Jaxb or Json providers into xml, json etc.
>
> I wasn't sure if I can get that content at response handlers level. If we
> can, can just give sample code that can retrieve from Message or Response.
>
> We already have a redis cache setup, and would be using it. Or else,
> echcache option that you had provided is exactly what i'm looking for.
>
> Thanks,
>
> Swarup
>
> --
> View this message in context:
> http://cxf.547215.n5.nabble.com/Caching-results-using-interceptor-tp5039950p5042149.html
> Sent from the cxf-user mailing list archive at Nabble.com.