I just want to use a spring bean within handleMessage() method which is called in handler-chain.xml.
This is my handler-chain.xml:
<jaxws:bindings>
<handler-chains xmlns="http://java.sun.com/xml/ns/javaee">
<!-- ====================== -->
<!-- service based handlers -->
<!-- ====================== -->
<handler-chain>
<handler>
<handler-name>CustomerHandler</handler-name>
<handler-class>com.test.ws.handler.CustomerHandler</handler-class>
</handler>
</handler-chain>
</handler-chains>
</jaxws:bindings>
And also this is my CustomerHandler.java class:
public class CustomerHandler implements SOAPHandler<SOAPMessageContext> {
#Autowired
public ServiceInvokeUtil serviceInvokeUtil;
public Set<QName> getHeaders() {
return null;
}
public void close(MessageContext context) {
}
public boolean handleFault(SOAPMessageContext context) {
logSoapMessage(context);
return false;
}
public boolean handleMessage(SOAPMessageContext context) {
Boolean isRequest = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
SOAPMessage soapMsg = context.getMessage();
// if this is a request, true for outbound messages, false for inbound
if (isRequest) {
try {
SOAPEnvelope soapEnv = soapMsg.getSOAPPart().getEnvelope();
SOAPHeader soapHeader = soapEnv.getHeader();
// if no header, add one
if (soapHeader == null) {
soapHeader = soapEnv.addHeader();
}
Boolean oa = serviceInvokeUtil.createRecord(SoapUtil.getRecordEntity());
SOAPElement userContextHeader = ConsumerHeaderHelper.createUserContextHeader(context);
soapHeader.addChildElement(userContextHeader);
}
soapMsg.saveChanges();
} catch (SOAPException e) {
System.err.println(e);
}
} else {
try {
SoapUtil.setSoapResponseHeader(soapMsg.getSOAPHeader());
} catch (SOAPException e) {
e.printStackTrace();
}
}
logSoapMessage(context);
return true;
}
This is my spring configuration xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ehcache="http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring
http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring/ehcache-spring-1.1.xsd">
<context:property-placeholder />
<bean id="serviceInvokeUtil" class="com.test.ws.util.ServiceInvokeUtil">
</bean>
When I am calling a web service, the spring bean serviceInvokeUtil is null.
How to use serviceInvokeUtil class as a spring bean within handleMessage method?
I extended SpringBeanAutowiringSupport to CustomerHandler class than it was solved. Like this: public class CustomerHandler extends SpringBeanAutowiringSupport implements SOAPHandler {.....
Spring will processes #Autowired annotation only if it will control creation of instance. In other words, your CustomerHandler have to be bean as well as ServiceInvokeUtil to force spring autowire it.
Related
I am trying to migrate a project from a traditional (working) Java servlet application to Spring MVC in the NetBeans IDE, but my program absolutely refuses to ping the Controller. On the client side, I see the following 404 errors:
index.do?displayType=table:1 Failed to load resource: the server responded with a status of 404 (Not Found)
index.do?displayType=table:1 Failed to load resource: the server responded with a status of 404 (Not Found)
I invoke the controller methods like so:
$.get("index.do","displayType=table", function( data ) {
jstring = JSON.parse(data.substr(12).slice(0, -1));
});
$.get("index.do","displayType=pivot",function(unparsedJSON) {});
$.post("index.do","jsonString=" + JSON.stringify(hot.getData()));
Below are my controller and xml configuration files:
MappingControl.java
package controllers;
import infoLoader.JsonWriter;
import infoLoader.getJSON;
import java.util.logging.Level;
import java.util.logging.Logger;
import static org.springframework.http.HttpMethod.GET;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
#Controller
#RequestMapping("/")
public class MappingControl {
#RequestMapping(value="/index.do", method=RequestMethod.GET)
public String populatePivotAndSheet(#RequestParam("displayType") String type) {
String returnedJSON = "";
try {
returnedJSON = getJSON.getJSON(type);
} catch (Exception ex) {
System.out.println("Unable to retrieve JSON");
}
return returnedJSON;
}
#RequestMapping(value="/index.do", method=RequestMethod.POST)
public void deliverSheet(#RequestParam("jsonString") String writableJSON) {
String returnedJSON = "";
JsonWriter.writeJSON(writableJSON);
}
}
applicationContext.xml
<?xml version='1.0' encoding='UTF-8' ?>
<!-- was: <?xml version="1.0" encoding="UTF-8"?> -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
</beans>
dispatcher-servlet.xml
<?xml version='1.0' encoding='UTF-8' ?>
<!-- was: <?xml version="1.0" encoding="UTF-8"?> -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd" xmlns:mvc="http://www.springframework.org/schema/mvc">
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/>
<!--
Most controllers will use the ControllerClassNameHandlerMapping above, but
for the index controller we are using ParameterizableViewController, so we must
define an explicit mapping for it.
-->
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="index.htm">indexController</prop>
</props>
</property>
</bean>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/jsp/"
p:suffix=".jsp" />
<!--
The index controller.
-->
<bean name="indexController"
class="org.springframework.web.servlet.mvc.ParameterizableViewController"
p:viewName="index" />
<mvc:resources mapping="/resources/**" location="/resources" />
<context:component-scan base-package="controllers" />
</beans>
I've been building this based on the default Spring-MVC template provided by NetBeans, so if any of you believe the template is poorly formatted and should be changed in some way, I would appreciate any input you might have.
Thanks so much for your time, guys, and let me know if anything is unclear.
You need add #ResponseBody to your method,due to in your case,you want to return the json data,if you missing #ResponseBody it will return to the view page,however you do not specify any view page in your code,thus will cause 404 error
#ResponseBody
#RequestMapping(value="/index.do", method=RequestMethod.GET)
public String populatePivotAndSheet(#RequestParam("displayType") String type) {
String returnedJSON = "";
try {
returnedJSON = getJSON.getJSON(type);
} catch (Exception ex) {
System.out.println("Unable to retrieve JSON");
}
return returnedJSON;
}
#ResponseBody
#RequestMapping(value="/index.do", method=RequestMethod.POST)
public void deliverSheet(#RequestParam("jsonString") String writableJSON) {
String returnedJSON = "";
JsonWriter.writeJSON(writableJSON);
}
Currently my batch has a static commit-interval (1000). We asked me to change it in order to commit once a data in my flat file get changed. So I should have a reader which reads lines from flat file, once it notice that this data has changed, it should process the read lines and writes in database.
I tried with completionPolicy as follows:
ReceptionCompletionPolicy.java:
public class ReceptionCompletionPolicy extends SingleItemPeekableItemReader<ReceptionLineFieldHelper> implements CompletionPolicy{
private ReceptionLineFieldHelper current;
public boolean isComplete(RepeatContext context) {
return ((ReaderRepeatContext) context).isComplete();
}
public boolean isComplete(RepeatContext context, RepeatStatus result) {
return ((ReaderRepeatContext) context).isComplete();
}
public RepeatContext start(RepeatContext parent) {
/*
* Set first item of the chunk for later comparison.
*/
this.current = invokePeek();
return new ReaderRepeatContext(parent);
}
public void update(RepeatContext context) {
/*
* Check if the step should finish.
* In this case when there are no more records to process.
*/
if (current == null) {
context.setCompleteOnly();
}
}
private ReceptionLineFieldHelper invokePeek() {
ReceptionLineFieldHelper peeked = null;
try {
peeked = peek();
} catch (Exception e) {
e.printStackTrace();
}
return peeked;
}
//custom RepeatContext
protected class ReaderRepeatContext extends RepeatContextSupport{
public ReaderRepeatContext(RepeatContext parent) {
super(parent);
}
public boolean isComplete() {
ReceptionLineFieldHelper next = null;
next = invokePeek();
if (next == null || !(next.getCode().equals(current.getCode()))) {
current = next;
return true;
}
return false;
}
}
}
ReceptionReader.java:
public class ReceptionReader implements ItemReader {
public Object read() {
return this.filterFile(inputFile);
}
}
reception.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:batch="http://www.springframework.org/schema/batch"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/batch
http://www.springframework.org/schema/batch/spring-batch-2.1.xsd">
<!-- import config Spring générale -->
<import
resource="classpath*:spring/batch-spring.xml" />
<batch:job id="reception" parent="simpleJob"
job-repository="jobRepository">
<!-- Déclaration step T01 -->
<batch:step id="t01" parent="simpleStep">
<batch:tasklet transaction-manager="transactionManager">
<batch:chunk reader="receptionReader"
writer="receptionProcessor"
chunk-completion-policy="receptionCompletionPolicy" />
</batch:tasklet>
</batch:step>
</batch:job>
<!--
*****************
* ETAPE T01 *
***************** -->
<!-- reader -->
<bean id="receptionReader"
class="com.reception.reader.ReceptionReader">
</bean>
<!-- writer -->
<bean id="receptionProcessor"
class="com.reception.processor.ReceptionProcessor">
</bean>
<!-- completionPolicy -->
<bean id="receptionCompletionPolicy"
class="com.reception.completionPolicy.ReceptionCompletionPolicy">
</bean>
</beans>
Apparently I have problem with completionPolicy at invokePeek() method. Does any one have an idea?
If there is an other way to reach my goal it will be welcome too.
This question has already an answer here but i've checked and the component:scan is set roperly for me so i don't really get what is the point here. The controller:
#Controller
#RequestMapping("view")
public class PortletController {
#RenderMapping
public String view(RenderRequest request, RenderResponse response, ModelMap model) {
ResourceURL baseResourceUrl = response.createResourceURL();
model.addAttribute("ajaxURL", baseResourceUrl.toString() + "&");
model.addAttribute("standalone", false);
model.addAttribute("portletId", getPortletId(request));
model.addAttribute("portletAppContextPath", request.getContextPath() + "/");
return "index";
}
The component scan element in the applicationcontext is:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<!-- DispatcherPortlet Context: defines this portlet's request-processing infrastructure -->
<!-- Autodetect annotated controllers -->
<context:component-scan base-package="com.package.of.controller"/>
</beans>
Any idea of why it could be not working?
I want to record execution time of my service method.
I think AOP is a easy way to do, so I wrote an Aspect:
#Aspect
public class ServiceLogAdviceAspect {
private static Logger LOG = LoggerFactory.getLogger(ServiceLogAdviceAspect.class);
#Around("execution(* com.j1.**.service.*(..))")
public Object doBasicProfilingTime(ProceedingJoinPoint joinPoint) throws Throwable {
String methodName = joinPoint.getSignature().getName();
Object target = joinPoint.getTarget();
long start = System.currentTimeMillis();
Object retVal = joinPoint.proceed();
long end = System.currentTimeMillis();
LOG.error(String.format("Invoke [%s$%s] Takes %d ms", target.getClass().getCanonicalName(), methodName, (end - start)));
return retVal;
}
}
and Spring config:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
default-autowire="byName">
<aop:aspectj-autoproxy/>
<bean id="logAdviceAspect"
class="com.j1.soa.common.aspect.ServiceLogAdviceAspect"></bean>
</beans>
But when I invoke the method
public ServiceMessage<GoodsDetailDto> getGoodDetail(GoodsDetailDto goodsDetailDto)
I get neither error output nor into the breakpoint.
EDIT
getGoodDetail is defined in class
com.j1.soa.resource.item.service.GoodsDetailServiceImpl
And I am calling it using Hessian RPC,
First defined spring bean of Remote Service in application-context-rpc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="goodsDetailService" class="org.springframework.remoting.caucho.HessianProxyFactoryBean">
<property name="serviceUrl" value="http://api.soa.item.j1.com/hessian/goodsDetailService" />
<property name="serviceInterface" value="com.j1.soa.resource.item.api.GoodsDetailService" />
<property name="readTimeout" value="6000"/>
</bean>
</beans>
Then defined it in client
#Autowired
private GoodsDetailService goodsDetailService;
And using it
GoodsDetailDto goodsDetailDto = new GoodsDetailDto();
goodsDetailDto.setGoodsId(NumericUtil.parseLong(goodsId));
goodsDetailDto.setProductId(NumericUtil.parseInt(productId));
goodsDetailDto.setSiteType(SiteType.MOBILE);
ServiceMessage<GoodsDetailDto> detailResult = goodsDetailService
.getGoodDetail(goodsDetailDto);
You should include logAdviceAspect in <aop:aspectj-autoproxy/>
<aop:aspectj-autoproxy>
<aop:include name="logAdviceAspect"/>
</aop:aspectj-autoproxy>
I created a web service using Apache cfx and spring, it works, but I need that the response include this header
<?xml version="1.0" encoding="UTF-8"?>
Right now the response is like this.
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:postEncuestaResponse xmlns:ns2="http://webservice.atomsfat.com/">
<respuestaEncuesta>
<dn>12315643154</dn>
<encuestaPosted>true</encuestaPosted>
<fecha>2009-09-30T16:32:33.163-05:00</fecha>
</respuestaEncuesta>
</ns2:postEncuestaResponse>
</soap:Body>
</soap:Envelope>
But should be like this
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:postEncuestaResponse xmlns:ns2="http://webservice.atomsfat.com/">
<respuestaEncuesta>
<dn>12315643154</dn>
<encuestaPosted>true</encuestaPosted>
<fecha>2009-09-30T16:32:33.163-05:00</fecha>
</respuestaEncuesta>
</ns2:postEncuestaResponse>
</soap:Body>
</soap:Envelope>
This is the configuration of the beans of spring that expose the service.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<jaxws:endpoint
id="encuestas"
implementor="webservice.serviceImpl"
address="/Encuestas" >
</jaxws:endpoint>
</beans>
this is the interface
import java.util.List;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
#WebService
public interface Encuestas {
#WebResult(name= "respuestaEncuesta")
RespuestaEncuestaMsg postEncuesta (#WebParam(name = "encuestaMsg") EncuestaMsg message);
}
Any ideas ?
Or use CXF build-in configuration capabilities.
Just add this IN your CXF Spring config :
<jaxws:properties>
<entry key="org.apache.cxf.stax.force-start-document">
<bean class="java.lang.Boolean">
<constructor-arg value="true"/>
</bean>
</entry>
</jaxws:properties>
Check the following
How can I add soap headers to the request/response?
Adding JAX-WS handlers to web services
Converting JAX-WS handlers to Apache CXF interceptors
then decide for one of the options and implement a handler/interceptor which adds what you need.
Well I implement a Handler, first I downloaded the examples from CXF and modified the logging Handler, and it works.
The configuration of spring :
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<jaxws:endpoint
id="encuestas"
implementor="com.webservice.EncuestasImpl"
address="/Encuestas">
<jaxws:handlers>
<bean class="com.webservice.HeaderHandler"/>
</jaxws:handlers>
</jaxws:endpoint>
And the code this is the code for the handler.
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.webservice;
import java.io.PrintStream;
import java.util.Map;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
/*
* This simple logical Handler will output the payload of incoming
* and outgoing messages.
*/
public class HeaderHandler implements SOAPHandler<SOAPMessageContext> {
private PrintStream out;
public HeaderHandler() {
setLogStream(System.out);
}
protected final void setLogStream(PrintStream ps) {
out = ps;
}
public void init(Map c) {
System.out.println("LoggingHandler : init() Called....");
}
public Set<QName> getHeaders() {
return null;
}
public boolean handleMessage(SOAPMessageContext smc) {
System.out.println("LoggingHandler : handleMessage Called....");
logToSystemOut(smc);
return true;
}
public boolean handleFault(SOAPMessageContext smc) {
System.out.println("LoggingHandler : handleFault Called....");
logToSystemOut(smc);
return true;
}
// nothing to clean up
public void close(MessageContext messageContext) {
System.out.println("LoggingHandler : close() Called....");
}
// nothing to clean up
public void destroy() {
System.out.println("LoggingHandler : destroy() Called....");
}
/*
* Check the MESSAGE_OUTBOUND_PROPERTY in the context
* to see if this is an outgoing or incoming message.
* Write a brief message to the print stream and
* output the message. The writeTo() method can throw
* SOAPException or IOException
*/
protected void logToSystemOut(SOAPMessageContext smc) {
Boolean outboundProperty = (Boolean)
smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outboundProperty.booleanValue()) {
out.println("\nOutbound message:");
} else {
out.println("\nInbound message:");
}
SOAPMessage message = smc.getMessage();
try {
message.setProperty(SOAPMessage.WRITE_XML_DECLARATION, "true");
message.writeTo(out);
out.println();
} catch (Exception e) {
out.println("Exception in handler: " + e);
}
}
}
Note: that in the try I use MessageContext.MESSAGE_OUTBOUND_PROPERTY like Justin suggested.
Folowing the links provided by jitter, I went to http://cxf.apache.org/faq.html#FAQ-HowcanIaddsoapheaderstotherequest%252Fresponse%253F and found the following solution:
// My object of the custom header
AuthenticationHeader aut = new AuthenticationHeader();
aut.setUserName("ws");
aut.setPassword("ws123");
IntegrationWS integration = new IntegrationWS();
List<Header> headers = new ArrayList<Header>();
Header dummyHeader;
try {
dummyHeader = new Header(new QName("http://www.company.com/ws/", "AuthenticationHeader"), auth, new JAXBDataBinding(AuthenticationHeader.class));
} catch (JAXBException e) {
throw new IllegalStateException(e);
}
headers.add(dummyHeader);
IntegrationWSSoap soapPort = integration.getIntegrationWSSoap12();
//client side:
((BindingProvider)soapPort).getRequestContext().put(Header.HEADER_LIST, headers);
ArrayOfBrand arrayBrand = soapPort.syncBrands();
I don't have Apache CXF specific knowledge, but the jax-ws way to add the xml declaration seems to be to make a handler and use SOAPMessage.setProperty() to turn that feature on:
message.setProperty(SOAPMessage.WRITE_XML_DECLARATION, "true");
You should be able to add a jax-ws handler to your endpoint by adding a jaxws:handlers element in that spring config.