I am trying to create Restful Webservice as a client of Message Driven Bean, But when i invoke the restful method its giving me following error when
Connection connection = connectionFactory.createConnection();
SEVERE: The RuntimeException could not be mapped to a response, re-throwing to the HTTP container
java.lang.NullPointerException
at com.quant.ws.GetConnection.startThread(GetConnection.java:99)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
here is the following code:
// Inside class declaration
#Resource(mappedName = "jms/testFactory")
private static ConnectionFactory connectionFactory;
#Resource(mappedName = "jms/test")
private static Queue queue;
Web services Method
#GET
#Path("startThread")
#Produces("application/xml")
public String startThread()
{
try{
Connection connection = connectionFactory.createConnection(); // its line number 99
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer producer = session.createProducer( queue);
Message message = session.createTextMessage();
message.setStringProperty("name", "start");
producer.send(message);
}catch(JMSException e){
System.out.println(e);
}
return "<data>START</data>";
}
Do i need to specify anything in sun-web.xml or web.xml ?
I think it depends on your applicationserver setup. Did you inject the connectionFactory somewhere above? Or did a context lookup?
connectionFactory is null. It needs to be initialised somehow.
I have solved it by replacing following code
try{
InitialContext ctx = new InitialContext();
queue = (Queue) ctx.lookup("jms/test");
QueueConnectionFactory factory =
(QueueConnectionFactory) ctx.lookup("jms/testFactory");
Connection connection = factory.createConnection();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer producer = session.createProducer( queue);
Message message = session.createTextMessage();
message.setStringProperty("name", "start");
producer.send(message);
}
catch(NamingException e){
System.out.println(e);
}
catch(JMSException e){
System.out.println(e);
}
Related
I am using this sample: https://github.com/Azure/azure-event-hubs-for-kafka/tree/master/tutorials/oauth/java/appsecret
I did some minor modifications in TestProducer class (add line 18 and line 26), I want to produce message to 2 different EVENT HUB namespaces (means creating 2 diffrent Kafka Producers for 2 bootstrap servers) in ONE console application, see code:
public class TestProducer {
//Change constant to send messages to the desired topic, for this example we use 'test'
private final static String TOPIC = "do.kafka.oauth";
private final static int NUM_THREADS = 1;
public static void main(String... args) throws Exception {
//Create Kafka Producer
final Producer<Long, String> producer = createProducer(false);
final Producer<Long, String> producer_auto = createProducer(true);
final ExecutorService executorService = Executors.newFixedThreadPool(NUM_THREADS);
//Run NUM_THREADS TestDataReporters
for (int i = 0; i < NUM_THREADS; i++){
executorService.execute(new TestDataReporter(producer, TOPIC));
executorService.execute(new TestDataReporter(producer_auto, TOPIC));
}
}
private static Producer<Long, String> createProducer(boolean isAuto) {
try{
Properties properties = new Properties();
if(isAuto)
properties.load(new FileReader("src/main/resources/producer_auto.config"));
else
properties.load(new FileReader("src/main/resources/producer.config"));
properties.put(ProducerConfig.CLIENT_ID_CONFIG, "KafkaExampleProducer");
properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, LongSerializer.class.getName());
properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
return new KafkaProducer<>(properties);
} catch (Exception e){
System.out.println("Failed to create producer with exception: " + e);
System.exit(0);
return null; //unreachable
}
}
}
Here is producer.config:
bootstrap.servers=advantcoeventhubs.servicebus.windows.net:9093
security.protocol=SASL_SSL
sasl.mechanism=OAUTHBEARER
sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required;
sasl.login.callback.handler.class=CustomAuthenticateCallbackHandler
and producer_auto.config:
bootstrap.servers=autoeventhubtesting.servicebus.windows.net:9093
security.protocol=SASL_SSL
sasl.mechanism=OAUTHBEARER
sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required;
sasl.login.callback.handler.class=CustomAuthenticateCallbackHandler
When I execute the code, the application can produce message to just the first namespace (advantcoeventhubs), and throw exception when produce message to the second namespace (autoeventhubtesting):
"ERROR NetworkClient [Producer clientId=KafkaExampleProducer] Connection to node -1 (autoeventhubtesting.servicebus.windows.net/13.66.138.74:9093) failed authentication due to: Invalid SASL mechanism response, server may be expecting a different protocol"
Please see attached picture for error here:
Invalid SASL mechanism response, server may be expecting a different protocol
Can any experts advise the root cause and work around solution?
Thank you so much!
I am facing strange issue where response as string not coming back from one service to another service. we have created microservices where one service is calling another service. i can see response printed in logs . after that line immediately i am returning that response but its coming back as null.
I created similar method with same code and it works fine. I have put code for calling service and service method from which i am returning response.
controller:
#RequestMapping(value = "/test/save", method = RequestMethod.POST)
#ResponseBody
public String save(#RequestBody Calculation calculation,
HttpServletRequest request) {
logger.info("In .save");
String result = "false";
try {
result = CalService.save(calculation);
logger.info("Response from service is :" + result);
} catch (Exception e) {
logger.error("Exception occured in save:", e);
}
return result;
}
method call client :
public String saveCal(Calculation calculation) {
String result = null;
try {
logger.info("In save");
MultiValueMap<String, String> headers = new LinkedMultiValueMap<String, String>();
headers.add("REMOTE_USER", "test");
HttpEntity<Calculation> request = new HttpEntity<Calculation>(Calculation, headers);
RestTemplate template = new RestTemplate();
template.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
result = template.postForObject(url+"/test/save", request, String.class);
} catch (Exception e) {
logger.error("Exception occured in SaveMddMd", e);
result = "fail";
}
logger.info("Save"+result);
return result;
}
result returned is success or failure.
I can see result printed in controller as success but when it comes back to client it prints as null. I created exact same method with different signature which returns result as success. we are using microservices here.
Jordan
Why is AWS SQS not a default connector for Apache Flink? Is there some technical limitation to doing this? Or was it just something that didn't get done? I want to implement this, any pointers would be appreciated
Probably too late for an answer to the original question... I wrote a SQS consumer as a SourceFunction, using the Java Messaging Service library for SQS:
SQSConsumer extends RichParallelSourceFunction<String> {
private volatile boolean isRunning;
private transient AmazonSQS sqs;
private transient SQSConnectionFactory connectionFactory;
private transient ExecutorService consumerExecutor;
#Override
public void open(Configuration parameters) throws Exception {
String region = ...
AWSCredentialsProvider credsProvider = ...
// may be use a blocking array backed thread pool to handle surges?
consumerExecutor = Executors.newCachedThreadPool();
ClientConfiguration clientConfig = PredefinedClientConfigurations.defaultConfig();
this.sqs = AmazonSQSAsyncClientBuilder.standard().withRegion(region).withCredentials(credsProvider)
.withClientConfiguration(clientConfig)
.withExecutorFactory(()->consumerExecutor).build();
this.connectionFactory = new SQSConnectionFactory(new ProviderConfiguration(), sqs);
this.isRunning = true;
}
#Override
public void run(SourceContext<String> ctx) throws Exception {
SQSConnection connection = connectionFactory.createConnection();
// ack each msg explicitly
Session session = connection.createSession(false, SQSSession.UNORDERED_ACKNOWLEDGE);
Queue queue = session.createQueue(<queueName>);
MessageConsumer msgConsumer = session.createConsumer(queue);
msgConsumer.setMessageListener(msg -> {
try {
String msgId = msg.getJMSMessageID();
String evt = ((TextMessage) msg).getText();
ctx.collect(evt);
msg.acknowledge();
} catch (JSMException e) {
// log and move on the next msg or bail with an exception
// have a dead letter queue is configured so this message is not lost
// msg is not acknowledged so it may be picked up again by another consumer instance
}
};
// check if we were canceled
if (!isRunning) {
return;
}
connection.start();
while (!consumerExecutor.awaitTermination(1, TimeUnit.MINUTES)) {
// keep waiting
}
}
#Override
public void cancel() {
isRunning = false;
// this method might be called before the task actually starts running
if (sqs != null) {
sqs.shutdown();
}
if(consumerExecutor != null) {
consumerExecutor.shutdown();
try {
consumerExecutor.awaitTermination(1, TimeUnit.MINUTES);
} catch (Exception e) {
//log e
}
}
}
#Override
public void close() throws Exception {
cancel();
super.close();
}
}
Note if you are using a standard SQS queue you may have to de-dup the messages depending on whether exactly-once guarantees are required.
Reference:
Working with JMS and Amazon SQS
At the moment, there is no connector for AWS SQS in Apache Flink. Have a look at the already existing connectors. I assume you already know about this, and would like to give some pointers. I was also looking for an SQS connector recently and found this mail thread.
Apache Kinesis Connector is somewhat similar to what you can implement on this. See whether you can get a start on this using this connector.
I have a code that acts as my subscriber. I have created durable subscriber. So due to this i am getting exception as
Exception in thread "main" javax.jms.JMSException: Error registering consumer: org.wso2.andes.AMQTimeoutException: Server did not respond in a timely fashion [error code 408: Request Timeout]
at org.wso2.andes.client.AMQSession$4.execute(AMQSession.java:2054)
at org.wso2.andes.client.AMQSession$4.execute(AMQSession.java:1997)
at org.wso2.andes.client.AMQConnectionDelegate_8_0.executeRetrySupport(AMQConnectionDelegate_8_0.java:305)
at org.wso2.andes.client.AMQConnection.executeRetrySupport(AMQConnection.java:621)
at org.wso2.andes.client.failover.FailoverRetrySupport.execute(FailoverRetrySupport.java:102)
at org.wso2.andes.client.AMQSession.createConsumerImpl(AMQSession.java:1995)
at org.wso2.andes.client.AMQSession.createConsumer(AMQSession.java:993)
at org.wso2.andes.client.AMQSession.createDurableSubscriber(AMQSession.java:1142)
at org.wso2.andes.client.AMQSession.createDurableSubscriber(AMQSession.java:1042)
at org.wso2.andes.client.AMQTopicSessionAdaptor.createDurableSubscriber(AMQTopicSessionAdaptor.java:73)
at xml.parser.Parser.subscribe(Parser.java:62)
at xml.parser.Parser.main(Parser.java:34)
But instead od durable when i create normal Subscriber, My code run good and there is no error. Why i am getting this error?
And one more question-How can i unsubscribe from the topic?
My code for Subscriber is:
package xml.parser;
import org.w3c.dom.*;
import javax.xml.xpath.*;
import javax.xml.namespace.NamespaceContext;
import javax.xml.parsers.*;
import java.io.IOException;
import org.xml.sax.SAXException;
import javax.jms.*;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.util.Properties;
public class Parser {
public static final String QPID_ICF = "org.wso2.andes.jndi.PropertiesFileInitialContextFactory";
private static final String CF_NAME_PREFIX = "connectionfactory.";
private static final String CF_NAME = "qpidConnectionfactory";
String userName = "admin";
String password = "admin";
private static String CARBON_CLIENT_ID = "carbon";
private static String CARBON_VIRTUAL_HOST_NAME = "carbon";
private static String CARBON_DEFAULT_HOSTNAME = "localhost";
private static String CARBON_BROKER_PORT = "5673";
String topicName = "myTopic";
public static void main(String[] args) throws NamingException,
JMSException, XPathExpressionException,
ParserConfigurationException, SAXException, IOException {
Parser queueReceiver = new Parser();
String message = queueReceiver.subscribe();
System.out.println("Got message from Queue ==> " + message);
}
public String subscribe() throws NamingException, JMSException {
String messageContent = "";
Properties properties = new Properties();
properties.put(Context.INITIAL_CONTEXT_FACTORY, QPID_ICF);
properties.put(CF_NAME_PREFIX + CF_NAME,
getTCPConnectionURL(userName, password));
properties.put("topic." + topicName, topicName);
System.out.println("getTCPConnectionURL(userName,password) = "
+ getTCPConnectionURL(userName, password));
InitialContext ctx = new InitialContext(properties);
// Lookup connection factory
TopicConnectionFactory connFactory = (TopicConnectionFactory) ctx
.lookup(CF_NAME);
TopicConnection topicConnection = connFactory.createTopicConnection();
topicConnection.start();
TopicSession topicSession = topicConnection.createTopicSession(false,
QueueSession.AUTO_ACKNOWLEDGE);
// Send message
// Topic topic = topicSession.createTopic(topicName);
Topic topic = (Topic) ctx.lookup(topicName);
javax.jms.TopicSubscriber topicSubscriber = topicSession
.createDurableSubscriber(topic,"topicQueue");
Message message = topicSubscriber.receive();
if (message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
System.out.println("textMessage.getText() = "
+ textMessage.getText());
messageContent = textMessage.getText();
}
topicSubscriber.close();
topicSession.close();
topicConnection.stop();
topicConnection.close();
return messageContent;
}
public String getTCPConnectionURL(String username, String password) {
return new StringBuffer().append("amqp://").append(username)
.append(":").append(password).append("#")
.append(CARBON_CLIENT_ID).append("/")
.append(CARBON_VIRTUAL_HOST_NAME).append("?brokerlist='tcp://")
.append(CARBON_DEFAULT_HOSTNAME).append(":")
.append(CARBON_BROKER_PORT).append("'").toString();
}
}
This is an issue in the MB 2.0.1 distribution with the durable subscribers. The reason for this is when the Parser class first runs, receives a message, and the subscriber is stopped, then when you start the Parser for the second time, it fails to starts the subscription back as the previous 'subscriber' entry is still there, and you will see the following in the terminal.The client will be timed out after few tries which is why you get the error log.
[2013-04-22 12:12:52,617] INFO {org.wso2.andes.server.protocol.AMQProtocolEngine} - Closing channel due to: Cannot subscribe to queue carbon:topicQueue as it already has an existing exclusive consumer
[2013-04-22 12:12:52,621] INFO {org.wso2.andes.server.protocol.AMQProtocolEngine} - Channel[1] awaiting closure - processing close-ok
[2013-04-22 12:12:52,621] INFO {org.wso2.andes.server.handler.ChannelCloseOkHandler} - Received channel-close-ok for channel-id 1
This issue has been fixed in MB 2.1.0 release which is expected to be out in the coming weeks. If you need please try your sample subscriber with MB 2.1.0 - Alpha version from here. This should work fine with that pack.
About unsubscribing from a topic add the following line into your Parser code and run back when you need to unsubscribe.
topicSubscriber.close();
**topicSession.unsubscribe("topicQueue"); // add the name used to identify the subscription in the place of "topicQueue"**
topicSession.close();
topicConnection.stop();
topicConnection.close();
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);
...
}