Can anyone tell me where the spring integration ws:inbound-gateway sets its SOAP Exception Resolver?
The outbound gateway has an attribute that I can set but the inbound does not.
I ant to set the Soap Fault Details before returning the SOAPFault back to the caller.
I have looked through the AbstractSoapFaultDefinitionExceptionResolver and tried to trace it back to somewhere where I could set it but I seem to be failing.
Any chance some one could point me in the right direction.
***********UPDATE**********
just as an FYI this was my final solution based on Artem's suggestion:
<bean id="exceptionResolver"
class="com.cloud.utils.CloudSoapFaultDefinitionResolver">
<property name="defaultFault" value="SERVER" />
</bean>
public class CloudMessagingSoapFaultDefinitionResolver extends SoapFaultAnnotationExceptionResolver {
private Logger log = LoggerFactory.getLogger(getClass());
private static final int THREE = 3;
/* (non-Javadoc)
* #see org.springframework.ws.soap.server.endpoint.AbstractSoapFaultDefinitionExceptionResolver#customizeFault(java.lang.Object, java.lang.Exception, org.springframework.ws.soap.SoapFault)
*/
#Override
protected void customizeFault(Object endpoint, Exception ex, SoapFault fault) {
SoapFaultDetail details = fault.addFaultDetail();
Method[] methods = ex.getClass().getDeclaredMethods();
if (ex instanceof MonitiseCloudServicesException) {
AbstractRuntimeException mcse = (AbstractRuntimeException) ex;
methods = mcse.getClass().getDeclaredMethods();
}
for(Method m:methods){
addDetailsElement(ex, details, m);
}
}
/**
* #param ex
* #param details
* #param m
*/
private void addDetailsElement(Exception ex, SoapFaultDetail details, Method m) {
if(m.getName().startsWith("get")){
SoapFaultDetailElement element = details.addFaultDetailElement(new QName(m.getName().substring(THREE)));
try {
element.addText((String) m.invoke(ex, new Object[]{}));
} catch (IllegalAccessException | IllegalArgumentException
| InvocationTargetException e) {
log.error("An error occured processing the SOAPFault detail node {}.",m.getName().substring(THREE));
}
}
}
}
Actually don't mix inbound and outbound parts. They are server and client respectivally, from Spring WS perspective. They have just a different nature for configuration.
So, on server part you can do that like this:
<bean id="exceptionResolver"
class="org.springframework.ws.soap.server.endpoint.SoapFaultMappingExceptionResolver">
<property name="defaultFault" value="SERVER"/>
<property name="exceptionMappings">
<value>
org.springframework.oxm.ValidationFailureException=CLIENT,Invalid request
</value>
</property>
</bean>
That's because any Spring Integration <ws:inbound-gateway> is a part of standard Spring WS MessageDispatcherServlet configuration:
<bean class="org.springframework.ws.server.endpoint.mapping.UriEndpointMapping"
p:defaultEndpoint-ref="ws-inbound-gateway"/>
And all Faul Resolving work is done by Spring WS.
Related
I've been digging around and I can't seem to find the answer to what I'm looking for at all.
I need to call an external web service when an order is placed in magento 2. I also need to use the order information in the call. I simply dont know what the right path is. Has anyone done this before?
I know the answer is late, but here is the solution that works for me, I have written observer for event checkout_submit_all_after.
Create file at path [CompanyName]/[ModuleName]/etc/events.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
<event name="checkout_submit_all_after">
<observer name="push_orders_to_purchaser" instance="RLTSquare\Quote\Observer\PushOrdersToPurchaserApi" />
</event>
</config>
Now in observer ([CompanyName]/[ModuleName]/observer/PushOrdersToPurchaserApi.php)
<?php
namespace RLTSquare\Quote\Observer;
use \Magento\Framework\Event\Observer;
use \Magento\Framework\Event\ObserverInterface;
use Magento\Framework\HTTP\Adapter\Curl;
class PushOrdersToPurchaserApi implements ObserverInterface
{
const MOCK_API = 'https://yourwebsite.com/insertorders';
protected $_request;
protected $_webApiRequest;
protected $_serviceOutputProcessor;
protected $_zendClientFactory;
public function __construct
(
\Magento\Framework\App\RequestInterface $request,
\Magento\Framework\Webapi\Rest\Request $webApiRequest,
\Magento\Framework\Webapi\ServiceOutputProcessor $serviceOutputProcessor,
\Magento\Framework\HTTP\ZendClientFactory $zendClientFactory
)
{
$this->_request = $request;
$this->_webApiRequest = $webApiRequest;
$this->_serviceOutputProcessor = $serviceOutputProcessor;
$this->_zendClientFactory = $zendClientFactory;
}
public function execute(Observer $observer)
{
/**
* #var \Magento\Sales\Model\Order[] $orders
*/
$orders = $observer->getOrders();
$encodedData = null;
if ($orders) {
$data = $this->_serviceOutputProcessor->convertValue($orders, '\Magento\Sales\Api\Data\OrderInterface[]');
$payload = \Zend_Json::encode($data, true);
$client = $this->_zendClientFactory->create();
$client->setUri(self::MOCK_API);
$client->setConfig(['maxredirects' => 0, 'timeout' => 30]);
$client->setRawData($payload);
$response = $client->request(\Zend_Http_Client::POST)->getBody();
//play with response here...
}
}
}
I'm using the spring schedule to do some full treatment at night, it should invoke a soap webServices and nothing else.
The program works fine on my local server, but not on PROD :
scheduler :
#Configuration
#EnableScheduling
public class ActivationScheduler {
private static final Logger LOGGER = LoggerFactory.getLogger(ActivationScheduler.class);
#Autowired
private ActivationService activationService;
/**
* un cron qui se lance automatiquement tous les soirs à 04h:00
*/
#Scheduled(cron = "0 20 11 * * *")
public void execute() {
try {
activationService.relanceAll();
} catch (Exception e) {
LOGGER.error(Constants.EXCEPTION_LABEL, e);
}
}
}
Exception :
2017-11-10 11:20:00 ERROR TaskUtils$LoggingErrorHandler:95 - Unexpected error occurred in scheduled task.
java.lang.NoClassDefFoundError: org/bouncycastle/jce/provider/JCEBlockCipher$AEADGenericBlockCipher
at org.bouncycastle.jce.provider.JCEBlockCipher.engineSetMode(Unknown Source)
at javax.crypto.Cipher$Transform.setModePadding(Cipher.java:374)
at javax.crypto.Cipher.getInstance(Cipher.java:533)
at sun.security.ssl.JsseJce.getCipher(JsseJce.java:229)
at sun.security.ssl.CipherBox.<init>(CipherBox.java:179)
at sun.security.ssl.CipherBox.newCipherBox(CipherBox.java:263)
at sun.security.ssl.CipherSuite$BulkCipher.newCipher(CipherSuite.java:505)
at sun.security.ssl.CipherSuite$BulkCipher.isAvailable(CipherSuite.java:572)
at sun.security.ssl.CipherSuite$BulkCipher.isAvailable(CipherSuite.java:527)
at sun.security.ssl.CipherSuite.isAvailable(CipherSuite.java:194)
at sun.security.ssl.SSLContextImpl.getApplicableCipherSuiteList(SSLContextImpl.java:346)
at sun.security.ssl.SSLContextImpl.getDefaultCipherSuiteList(SSLContextImpl.java:304)
at sun.security.ssl.SSLSocketImpl.init(SSLSocketImpl.java:626)
at sun.security.ssl.SSLSocketImpl.<init>(SSLSocketImpl.java:537)
at sun.security.ssl.SSLSocketFactoryImpl.createSocket(SSLSocketFactoryImpl.java:72)
at sun.net.www.protocol.https.HttpsClient.createSocket(HttpsClient.java:405)
at sun.net.NetworkClient.doConnect(NetworkClient.java:162)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:432)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:527)
at sun.net.www.protocol.https.HttpsClient.<init>(HttpsClient.java:264)
at sun.net.www.protocol.https.HttpsClient.New(HttpsClient.java:367)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.getNewHttpClient(AbstractDelegateHttpsURLConnection.java:191)
at sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1105)
at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:999)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:177)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream0(HttpURLConnection.java:1283)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1258)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:250)
at org.springframework.ws.transport.http.HttpUrlConnection.getRequestOutputStream(HttpUrlConnection.java:89)
at org.springframework.ws.transport.AbstractSenderConnection$RequestTransportOutputStream.createOutputStream(AbstractSenderConnection.java:87)
at org.springframework.ws.transport.TransportOutputStream.getOutputStream(TransportOutputStream.java:41)
at org.springframework.ws.transport.TransportOutputStream.write(TransportOutputStream.java:64)
at com.sun.xml.internal.messaging.saaj.soap.MessageImpl.writeTo(MessageImpl.java:1314)
at org.springframework.ws.soap.saaj.SaajSoapMessage.writeTo(SaajSoapMessage.java:275)
at org.springframework.ws.transport.AbstractWebServiceConnection.send(AbstractWebServiceConnection.java:46)
at org.springframework.ws.client.core.WebServiceTemplate.sendRequest(WebServiceTemplate.java:658)
at org.springframework.ws.client.core.WebServiceTemplate.doSendAndReceive(WebServiceTemplate.java:606)
at org.springframework.ws.client.core.WebServiceTemplate.sendAndReceive(WebServiceTemplate.java:555)
at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:390)
at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:383)
at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:373)
I googled the exception, so I found some poeple talking about bouncycastle, I added the last version but it does'nt solve my problem and i had the same exception.
I'm using also dynamicreports 5.0.0 in the project and i excluded bouncycastle (bcprov-jdk14, bcmail-jdk14, bctsp-jdk14)
The last info that can be utile, the ws invoked have SSL security.
Thanks,
How can I user persistency in my REST application?
I want to use #Inject and #PersistenceUnit annotation to instantiate my needed PersistencyManager object,
by when I call the persistency functionality by REST service I get an error:
[2014-03-15 05:05:45,472] Artifact CubieboardGPIO:war: Error during artifact deployment. See server log for details.
[2014-03-15 05:05:45,473] Artifact CubieboardGPIO:war: javax.ejb.EJBException: The bean encountered a non-application exception; nested exception is:
org.apache.openejb.OpenEJBRuntimeException: java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/]]
This is my Rest:
#Inject
private PersistenceManager persistenceManager;
#GET
#Path("/activate")
public String activate(#QueryParam("pin") int pin) {
persistenceManager = new PersistenceManager();
// URI : /cubieboard/gpio/activate?pin=67
String[] messages = _activate(pin);
StringBuilder sb = new StringBuilder();
sb.append(ConfigurationManager.getConfiguration("ACTIVATE_MESSAGE")+"\n");
sb.append("Persistence:\t"); sb.append(messages[0]); sb.append("\n");
sb.append("Terminal Response:\t"); sb.append(messages[1]); sb.append("\n");
return sb.toString();
}
This is PersisteneManager:
#Stateless
public class PersistenceManager {
#PersistenceUnit(name = "cubieDB")
private static EntityManagerFactory factory;
private EntityManager em;
public PersistenceManager(){
// factory = Persistence.createEntityManagerFactory(ConfigurationManager.getConfiguration("PERSISTENCE_UNIT_NAME"));
// factory = Persistence.createEntityManagerFactory("cubieDB");
em = factory.createEntityManager();
}
public List<Operation> getAllOperations() {
Query q = em.createQuery("SELECT op FROM Operation op");
List<Operation> ops = q.getResultList();
return ops;
}
public void persist(Operation operation) {
em.getTransaction().begin();
em.persist(operation);
em.getTransaction().commit();
}
public void deleteAll(){
em.getTransaction().begin();
Query q = em.createNativeQuery("DELETE FROM Operation");
q.executeUpdate();
em.getTransaction().commit();
}
#Override
protected void finalize() throws Throwable {
super.finalize();
em.close();
}
}
And this is my persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
version="2.1">
<persistence-unit name="cubieDB" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>com.sakhoshdel.cubieboard.gpio.persistence.Operation</class>
<properties>
<!--<property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>-->
<property name="eclipselink.ddl-generation" value="create-tables"/>
<!--<property name="javax.persistence.schema-generation-action" value="drop-and-create"/>-->
<!--<property name="javax.persistence.schema-generation-target" value="database-and-scripts"/>-->
<property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver" />
<property name="javax.persistence.jdbc.url" value="jdbc:derby:cubieDB;create=true" />
</properties>
</persistence-unit>
</persistence>
Also when I call the persistence functionality from a normal class it runs. but when I want to deploy it I get error. I am using TomEE for application server.
Thank you
Well ejb constructor shouldnt be used (shouldnt even be called in last versions). Injection of static field is not recommanded neither.
Finally maybe just use a jta persistence unit and remove the em.getTransaction calls.
Side note: tomee comes with openjpa so you need to provide eclipselink if you want it
I am logging RequestXML for a webservice client using SoapHandler as follows
public boolean handleMessage(SOAPMessageContext smc) {
logToSystemOut(smc);
return true;
}
private 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.writeTo(out);
out.println("");
} catch (Exception e) {
out.println("Exception in handler: " + e);
}
}
Got a new requirenment to add this xml to DB along with some extra values(which are not present in the xml). Is there any way I can pass few additional fields to above soap handler (in handleMessage method)?
Please note that changing the xml/WSDL or adding this to SOAP message header is not an option for me as it is owned by other interface. Any other solution?
Thanks!
You can cast your service class to a class of type "BindingProvider". In this form you can use it to assign it objects which you can access later from your SOAPHandler. Another useful usage is that you also can change the endPoint URL this way.
Before calling the service you do:
MySoapServicePortType service = new MySoapService().getMySoapServicePort();
BindingProvider bp = (BindingProvider)service;
MyTransferObject t = new MyTransferObject();
bp.getRequestContext().put("myTransferObject", t);
TypeResponse response = service.doRequest();
SOAPMessage message = t.getRequestMessage(message);
From your logging function you do:
private void logToSystemOut(SOAPMessageContext smc) {
...
MyTransferObject t = (MyTransferObject) messageContext.get("myTransferObject");
if (outboundProperty.booleanValue())
t.setRequestMessage(message);
else
t.setResponseMessage(message);
...
}
I'm trying to modify SOAP body for an outbound ws client SOAP message, from an application which is deployed on JBoss 6.1.0. Final.
There is a registered HandlerResolver for that purpose, which has the following code:
public boolean handleMessage(SOAPMessageContext messagecontext) {
Boolean outbound = (Boolean) messagecontext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outbound) {
try {
SOAPMessage soapMessage = messagecontext.getMessage();
SOAPBody soapBody = soapMessage.getSOAPBody();
Node firstChild = soapBody.getFirstChild();
String timeStamp = getTimestamp();
String signature = getSignature(firstChild.getLocalName(), timeStamp, secretBytes);
SOAPFactory factory = SOAPFactory.newInstance();
SOAPElement signatureElement = factory.createElement("Signature");
System.out.println(signature);
signatureElement.addTextNode(signature);
SOAPElement timestampElement = factory.createElement("Timestamp");
timestampElement.addTextNode(timeStamp);
firstChild.appendChild(signatureElement);
firstChild.appendChild(timestampElement);
} catch(SOAPException se) {
throw new RuntimeException("SOAPException was thrown.", se);
}
}
return true;
}
However, it throws this exception:
17:59:35,527 WARN [org.apache.cxf.jaxws.handler.HandlerChainInvoker] HANDLER_RAISED_RUNTIME_EXCEPTION: org.w3c.dom.DOMException: WRONG_DOCUMENT_ERR: A node is used in a different document than the one that created it.
at com.sun.org.apache.xerces.internal.dom.ParentNode.internalInsertBefore(Unknown Source) [:1.6.0_27]
at com.sun.org.apache.xerces.internal.dom.ParentNode.insertBefore(Unknown Source) [:1.6.0_27]
at com.sun.org.apache.xerces.internal.dom.NodeImpl.appendChild(Unknown Source) [:1.6.0_27]
for this line:
firstChild.appendChild(signatureElement);
This code worked fine with JBoss 5.1.0.
Any ideas?
Thanks.
The difference between Axis(used in JBoss 5.1) and Cxf(used in JBoss 6.1.0 as default) frameworks creates this problem. That's why this code worked fine with JBoss 5.1.0.
Here is the solution.