SOAP JAXWS client intermittent error calling services - soap

I have a webapp with SpringBoot 2.2.6, Java 8, JBoss 7.2 EAP, now for testing purpose I start my app with bootdashboard (and so with tomcat).
I have to call SOAP WebServices which the customer exposes. With this plugin:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<goals>
<goal>wsimport</goal>
</goals>
</execution>
</executions>
<configuration>
<wsdlDirectory>${project.basedir}/src/main/resources/</wsdlDirectory>
<packageName>it.pegaso2000.agevolo.sace.ws.client</packageName>
<sourceDestDir>
${project.build.directory}/generated-sources/
</sourceDestDir>
</configuration>
</plugin>
I have created my client. Now I have added a configuration classes as below:
#Configuration
public class SOAPClientConfiguration {
#Value("${jks.auth.path}")
private String jksPath;
#Value("${jks.auth.pass}")
private String jksPass;
private final URL url = getClass().getClassLoader().getResource("customer.wsdl");
#Bean
public MainServices mainServices() {
try {
SSLContext sc = SSLContext.getInstance("TLSv1.2");
KeyManagerFactory kmf = KeyManagerFactory.getInstance( KeyManagerFactory.getDefaultAlgorithm() );
KeyStore ks = KeyStore.getInstance("JKS");
ks.load( new FileInputStream(jksPath), jksPass.toCharArray() );
kmf.init( ks, jksPass.toCharArray() );
sc.init( kmf.getKeyManagers(), null, null );
GaranzieItaliaApi api = new GaranzieItaliaApi(url);
GaranzieItaliaServices port = api.getGaranzieItaliaApiPort();
((BindingProvider) port).getRequestContext().put(
"com.sun.xml.internal.ws.transport.https.client.SSLSocketFactory", sc.getSocketFactory() );
return port;
} catch (NoSuchAlgorithmException e) {
log.error(e.getLocalizedMessage(), e);
} catch (KeyStoreException e) {
log.error(e.getLocalizedMessage(), e);
} catch (CertificateException e) {
log.error(e.getLocalizedMessage(), e);
} catch (FileNotFoundException e) {
log.error(e.getLocalizedMessage(), e);
} catch (IOException e) {
log.error(e.getLocalizedMessage(), e);
} catch (UnrecoverableKeyException e) {
log.error(e.getLocalizedMessage(), e);
} catch (KeyManagementException e) {
log.error(e.getLocalizedMessage(), e);
}
return null;
}
}
Now I autowire the MainServices (created by plugin) inside my #Service.
It works but I cannot do consecutive calls without having back the 401 Unauthorize error!
I have read several articles regarding keep-alive header but I still haven't been able to make it work.
I have tried adding headers as follow:
Map<String, List<String>> headers = new HashMap<>();
headers.put("Connection", Collections.singletonList("Keep-Alive"));
headers.put("keep-alive", Collections.singletonList("timeout=10"));
also
headers.put("keep-alive", Collections.singletonList("timeout=60000"));
or
headers.put("keep-alive", Collections.singletonList("timeout=10, max = 1"));
but nothing works. Any help is appreciated

Related

jboss eap 7 - Post message to IBM MQ with resource adapter

I have installed WMQ JMS resource adapter (9.0.4) to my JBOSS EAP 7 standalone-full.xml & created connection factory and admin object to it.
/subsystem=resource-adapters/resource-adapter=ibm-mq-resource-adapter:add(archive=wmq.jmsra-9.0.4.0.rar, transaction-support=NoTransaction)
/subsystem=resource-adapters/resource-adapter=ibm-mq-resource-adapter/admin-objects=queue-ao1:add(class-name=com.ibm.mq.connector.outbound.MQQueueProxy, jndi-name=java:jboss/outbound)
/subsystem=resource-adapters/resource-adapter=ibm-mq-resource-adapter/admin-objects=queue-ao1/config-properties=baseQueueName:add(value=TEST1)
/subsystem=resource-adapters/resource-adapter=ibm-mq-resource-adapter/admin-objects=queue-ao1/config-properties=baseQueueManagerName:add(value=TESTMANAGER)
Connection definition:
<connection-definition class-name="com.ibm.mq.connector.outbound.ManagedConnectionFactoryImpl" jndi-name="java:jboss/mqSeriesJMSFactoryoutbound" tracking="false" pool-name="mq-cd">
<config-property name="channel">
SYSTEM.DEF.XXX
</config-property>
<config-property name="hostName">
XX-XXX
</config-property>
<config-property name="transportType">
CLIENT
</config-property>
<config-property name="queueManager">
TESTMANAGER
</config-property>
<config-property name="port">
1414
</config-property>
</connection-definition>
In my understanding, If I post a message to the outbound queue from the connection factory mqSeriesJMSFactoryoutbound, I should be able to reach IBM MQ. I tried with below code to look up connection factory but I am getting naming notfound exception. Please help
public class TestQueueConnection {
// Set up all the default values
private static final String DEFAULT_MESSAGE = "Hello, World! successfull";
private static final String DEFAULT_CONNECTION_FACTORY = "java:jboss/mqSeriesJMSFactoryoutbound";
private static final String DEFAULT_DESTINATION = "java:jboss/outbound";
private static final String DEFAULT_MESSAGE_COUNT = "1";
private static final String DEFAULT_USERNAME = "jmsuser";
private static final String DEFAULT_PASSWORD = "jmsuser123";
private static final String INITIAL_CONTEXT_FACTORY = "org.jboss.naming.remote.client.InitialContextFactory";
private static final String PROVIDER_URL = "http-remoting://127.0.0.1:8070";
public static void main(String[] args) throws JMSException {
Context namingContext = null;
try {
String userName = System.getProperty("username", DEFAULT_USERNAME);
String password = System.getProperty("password", DEFAULT_PASSWORD);
// Set up the namingContext for the JNDI lookup
final Properties env = new Properties();
env.put(Context.INITIAL_CONTEXT_FACTORY, INITIAL_CONTEXT_FACTORY);
env.put(Context.PROVIDER_URL, System.getProperty(Context.PROVIDER_URL, PROVIDER_URL));
namingContext = new InitialContext(env);
// Perform the JNDI lookups
String connectionFactoryString = System.getProperty("connection.factory", DEFAULT_CONNECTION_FACTORY);
namingContext.lookup(connectionFactoryString);
QueueConnectionFactory connectionFactory = (QueueConnectionFactory)
JMSContext jmsContext = connectionFactory.createContext(DEFAULT_USERNAME, DEFAULT_PASSWORD);
Queue destination = (Queue) namingContext.lookup(DEFAULT_DESTINATION);
jmsContext.createProducer().send(destination, DEFAULT_MESSAGE);
System.out.println("><><><><><><>< MESSAGE POSTED <><><><><><><>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" );
} catch (NamingException e) {
e.printStackTrace();
} finally {
if (namingContext != null) {
try {
namingContext.close();
} catch (NamingException e) {
}
}
}
}
Made couple of changes to the above.
In connection-definition, instead of com.ibm.mq.connector.outbound.ManagedConnectionFactoryImpl, used ManagedQueueConnectionFactoryImpl to avoid class cast exception at runtime.
Connection factories created by RA are not accessible outside of its JVM. Written a servlet to access these connection factory. I am able to connect with below piece of code.
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.getWriter().append("Served at: ").append(request.getContextPath());
Context namingContext = null;
String connectionFactoryString = "mqSeriesJMSFactoryoutbound";
String queueName = "outbound";
MessageProducer producer = null;
Session session = null;
Connection conn =null;
try {
namingContext = new InitialContext();
QueueConnectionFactory connectionFactory = (QueueConnectionFactory) namingContext.lookup(connectionFactoryString);
Queue destination = (Queue) namingContext.lookup(queueName);
conn = connectionFactory.createConnection();
session = conn.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
producer = session.createProducer(destination);
TextMessage message = session.createTextMessage();
message.setText(msg);
producer.send(message,
Message.DEFAULT_DELIVERY_MODE,
Message.DEFAULT_PRIORITY,
Message.DEFAULT_TIME_TO_LIVE);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally {
// Close the message producer
try {
if (producer != null) producer.close();
}
catch (JMSException e) {
System.err.println("Failed to close message producer: " + e);
}
// Close the session
try {
if (session != null) session.close();
}
catch (JMSException e) {
System.err.println("Failed to close session: " + e);
}
// Close the connection
try {
if(conn != null)
conn.close();
}
catch (JMSException e) {
System.err.println("Failed to close connection: " + e);
}
}
}

ConnectionFactory throwing errors when shared

I've a very simple application that adds messages to a queue and reads them using a MessagerListener.
Edit: I was testing this on a single instance of Artemis that had been setup as part of a two instance cluster on docker.
I want to create the ConnectionFactory once and reuse it for all producers and consumers in the application.
I have created the ConnectionFactory and stored it in a static variable (singleton) so it can be accessed from anywhere.
The aim is that the client use this shared connection factory to create a new connection when required.
However, I have noticed that doing this causes a "Failed to create session factory" when trying to create a new connection.
javax.jms.JMSException: Failed to create session factory
at org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory.createConnectionInternal(ActiveMQConnectionFactory.java:886)
at org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory.createConnection(ActiveMQConnectionFactory.java:299)
at com.test.artemistest.jms.QueueTest2.getMessagesFromQueue(QueueTest2.java:137)
at com.test.artemistest.jms.QueueTest2.access$000(QueueTest2.java:61)
at com.test.artemistest.jms.QueueTest2$1.run(QueueTest2.java:75)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:830)
Caused by: ActiveMQNotConnectedException[errorType=NOT_CONNECTED message=AMQ219007: Cannot connect to server(s). Tried with all available servers.]
at org.apache.activemq.artemis.core.client.impl.ServerLocatorImpl.createSessionFactory(ServerLocatorImpl.java:690)
at org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory.createConnectionInternal(ActiveMQConnectionFactory.java:884)
If I create a connection factory per call this error does not occur.
Doing this seems very inefficient.
I've recreated a similar issue below.
If I create the connection factory in the main method the error occurs.
However if created just before use in a method it works as expected.
If I add two listeners the error occurs even though they are in separate threads. Could it be linked to the fact the connections are not closed in the consumers but are in the producers?
Why is this the case and do you recommend sharing the connection factory?
Thanks
public class QueueTest2 {
private static boolean shutdown = false;
private static ConnectionFactory cf;
public static void main(String[] args) {
// uncomment below for error to occur
// QueueTest2.getConnectionFactory("localhost", 61616);
ExecutorService executor = Executors.newCachedThreadPool();
executor.execute(new Runnable() {
#Override
public void run() {
getMessagesFromQueue("localhost", 61616);
while (!shutdown) {
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("getMessagesFromQueue shutdown");
}
});
addMessagesToQueue("localhost", 61616);
// uncommenting below also causes the issue
// executor.execute(new Runnable() {
// #Override
// public void run() {
// getMessagesFromQueue("localhost", 61616);
// while (!shutdown) {
// try {
// Thread.sleep(1000L);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
// System.out.println("getMessagesFromQueue shutdown");
// }
// });
addMessagesToQueue("localhost", 61616);
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
shutdown = true;
executor.shutdownNow();
}
private static void addMessagesToQueue(String host, int port) {
ConnectionFactory cf2 = getConnectionFactory(host, port);
Connection connection = null;
Session sessionQueue = null;
try {
connection = cf2.createConnection("artemis", "password");
connection.setClientID("Producer");
sessionQueue = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
Queue orderQueue = sessionQueue.createQueue("exampleQueue");
MessageProducer producerQueue = sessionQueue.createProducer(orderQueue);
connection.start();
// send 100 messages
for (int i = 0; i < 100; i++) {
TextMessage message = sessionQueue.createTextMessage("This is an order: " + i);
producerQueue.send(message);
}
} catch (JMSException ex) {
Logger.getLogger(QueueTest2.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
if (sessionQueue != null) {
sessionQueue.close();
}
} catch (JMSException ex) {
Logger.getLogger(QueueTest2.class.getName()).log(Level.SEVERE, null, ex);
}
try {
if (connection != null) {
connection.close();
}
} catch (JMSException ex) {
Logger.getLogger(QueueTest2.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
private static void getMessagesFromQueue(String host, int port) {
ConnectionFactory cf2 = getConnectionFactory(host, port);
Connection connection2 = null;
Session sessionQueue2;
try {
connection2 = cf2.createConnection("artemis", "password");
connection2.setClientID("Consumer2");
sessionQueue2 = connection2.createSession(false, Session.CLIENT_ACKNOWLEDGE);
Queue orderQueue = sessionQueue2.createQueue("exampleQueue");
MessageConsumer consumerQueue = sessionQueue2.createConsumer(orderQueue);
consumerQueue.setMessageListener(new MessageHandlerTest2());
connection2.start();
Thread.sleep(5000);
} catch (JMSException ex) {
Logger.getLogger(QueueTest2.class.getName()).log(Level.SEVERE, null, ex);
} catch (InterruptedException ex) {
Logger.getLogger(QueueTest2.class.getName()).log(Level.SEVERE, null, ex);
}
}
private static ConnectionFactory getConnectionFactory(String host, int port) {
if (cf == null) {
Map<String, Object> connectionParams2 = new HashMap<String, Object>();
connectionParams2.put(TransportConstants.PORT_PROP_NAME, port);
connectionParams2.put(TransportConstants.HOST_PROP_NAME, host);
TransportConfiguration transportConfiguration = new TransportConfiguration(NettyConnectorFactory.class
.getName(), connectionParams2);
cf = ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, transportConfiguration);
}
return cf;
}
}
class MessageHandlerTest2 implements MessageListener {
#Override
public void onMessage(Message message) {
try {
System.out.println("new message: " + ((TextMessage) message).getText());
message.acknowledge();
} catch (JMSException ex) {
Logger.getLogger(MessageHandlerTest2.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
I've run your code, but I don't see any errors. My guess is that there may be a timing issue related to concurrency. Try adding synchronized to your getConnectionFactory method since it can theoretically be called concurrently by multiple threads in your application, e.g.:
private synchronized static ConnectionFactory getConnectionFactory(String host, int port)
I have found a solution that works on a clustered environment and docker.
It involves using the "pooled-jms" connection pool. Something I had planned to use anyway.
Although it does not explain the issues I was seeing above, it is at least a work around until I can investigate further.
The "WARN: AMQ212064: Unable to receive cluster topology " mentioned above appears to have been a red herring as it went away as quickly as it appeared.

Using java nio in java ee

I want to use java nio in java ee.
But I don't know how to do it right.
I need to after server has deploy java.nio.selector always listens the port and processing socket connection.
I try do it there:
#Singleton
#Lock(LockType.READ)
public class TaskManager {
private static final int LISTENINGPORT;
static {
LISTENINGPORT = ConfigurationSettings.getConfigureSettings().getListeningPort();
}
private ArrayList<ServerCalculationInfo> serverList;
public TaskManager() {
serverList = new ArrayList<ServerCalculationInfo>();
select();
}
#Asynchronous
public void select() {
try {
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
Selector selector = Selector.open();
serverSocketChannel.configureBlocking(false);
serverSocketChannel.socket().bind(new InetSocketAddress(LISTENINGPORT));
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
try {
selector.select();
} catch (IOException ex) {
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
break;
}
Iterator it = selector.selectedKeys().iterator();
while (it.hasNext()) {
SelectionKey selKey = (SelectionKey) it.next();
it.remove();
try {
processSelectionKey(serverSocketChannel, selKey);
} catch (IOException e) {
serverList.remove(serverCalculationInfo);
}
}
}
} catch (IOException e) {
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, e);
} catch (Exception e) {
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, e);
}
}
}
It don't work correctly. The process hangs during deploy and redeploy application possible only after restart Glassfish.
How can I do right it?
It works correctly if invoke #Asynchronous method from the #PostConstructor:
#PostConstruct
public void postTaskManager() {
serverList = new ArrayList<ServerCalculationInfo>();
select();
}
instead of invoke it from constructor.
But class must be without #Startup annotation.

A network related error or instance-specific error occured while establishing a connection to sql server

This is the error which arises when I tried to debug an application under Visual C# 2010
I write that code to retrieve some rows from a database table, I already attached the two well known databases Pubs and Northwind to the db explorer, but the error remains
class Author
{
SqlConnection _pubConnection;
string _connString;
public Author()
{
_connString = "Data Source=./INSTANCE2;Initial Catalog=pubs;Integrated Security=True";
_pubConnection = new SqlConnection();
_pubConnection.ConnectionString = _connString;
}
public int CountAuthors()
{
try
{
SqlCommand pubCommand = new SqlCommand();
pubCommand.Connection = _pubConnection;
pubCommand.CommandText = "Select Count(au_id) from authors";
_pubConnection.Open();
return (int)pubCommand.ExecuteScalar();
}
catch (SqlException ex)
{
throw ex;
}
finally
{
if (_pubConnection != null)
{
_pubConnection.Close();
}
}
}
}
static void Main(string[] args)
{
try
{
Author author = new Author();
Console.WriteLine(author.CountAuthors());
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.ReadLine();
}
}
the Connection string isn't ok , i correct it and it works fine

webservice SOAP message Monitor or logging

Could some one tell me how to capture SOAP messages passed between the client and the server webservice applications.
I tried using both tools.
pocket soap
http://www.pocketsoap.com/pocketsoap/
Fiddler
http://www.fiddlertool.com/fiddler/
I may miss some settings, it is not working for me.
help will be more appreciated.
Try tcpmon.
soapUI integrates with tcpmon, and may provide a nicer interface for you.
See also; You can try the MS Visual Roundtrip Analyzer analyzer as well.
if you're interested, you can write a handler in Java which extends the GenericSOAPHandler class, and print the output to wherever you like. In this (simple) case, the server log:
#SuppressWarnings("rawtypes")
public class MyHandler extends GenericSOAPHandler {
private void print(InputStream input, OutputStream out) throws Exception {
try {
DocumentBuilder parser;
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
parser = factory.newDocumentBuilder();
Document document = parser.parse(input);
Transformer serializer = TransformerFactory.newInstance().newTransformer();
serializer.setOutputProperty(OutputKeys.INDENT, "yes");
serializer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
serializer.transform(new DOMSource(document), new StreamResult(out));
} catch (TransformerException e) {
// A fatal error occurred
throw new Exception(e);
}
}
#Override
protected boolean handleInbound(MessageContext msgContext) {
SOAPMessageContext soapMessageCtx = (SOAPMessageContext) msgContext;
SOAPMessage soapMessage = soapMessageCtx.getMessage();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try {
soapMessage.writeTo(outputStream);
byte[] array = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(array);
System.out.println("SOAP request message:\n");
print(inputStream, System.out);
} catch (SOAPException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
#Override
protected boolean handleOutbound(MessageContext msgContext) {
SOAPMessageContext soapMessageCtx = (SOAPMessageContext) msgContext;
SOAPMessage soapMessage = soapMessageCtx.getMessage();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try {
soapMessage.writeTo(outputStream);
byte[] array = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(array);
System.out.println("SOAP response message:\n");
print(inputStream, System.out);
} catch (SOAPException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
}
You also need to make sure your handler is included in the jaxws-handlers-server.xml of your server implementation:
<handler-chains xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee javaee_web_services_1_2.xsd">
<handler-chain>
<protocol-bindings>##SOAP11_HTTP</protocol-bindings>
<handler>
<handler-name>DebugHandler</handler-name>
<handler-class>handlers.MyHandler</handler-class>
</handler>
</handler-chain>
</handler-chains>
Here my code in C++ for retrieve xml message using Soap Toolkit 3.0 before sending.
.
.
.
Serializer->EndEnvelope();
/* ___________________ */
char * bufferxml = NULL;
_variant_t punt = _variant_t((IUnknown*)Serializer);
punt.lVal += 48;
_variant_t punt1 = *punt.ppunkVal;
punt1.lVal += 32;
_variant_t punt2 = *punt1.ppunkVal;
punt2.lVal += 4;
memcpy(&bufferxml, (char *) *punt2.ppunkVal, sizeof(char *));
punt2.lVal += 4;
int lengxml = *(punt2.pintVal);
bufferxml[lengxml] = '\0';
/* ___________________ */
// Send the message to the web service
Connector->EndMessage();
.
.
.
punt.Detach();
punt1.Detach();
punt2.Detach();
punt.Clear();
punt1.Clear();
punt2.Clear();
Serializer.Release();
.
.
.
I hope really help you, it´s my design and it had worked for me.
There is also TCP/IP Monitor which comes bundled with WTP plugin for eclipse which allows you to set up a monitor on a port to look into the SOAP requests.