I am new to MQ programmimg. As per my requirement I am trying to put a sample XML message in a queue and expecting a response back from the response queue.
I can see that the associated channel is opening for a short duration, for a few seconds and then getting closed. Please find below the code I am using to put the message in queue. Request your valuable inputs in getting this issue resolved.
Error:
Process(12908.13579) User(abc) Program(amqrmppa)
Host(hostname)
AMQ9208: Error on receive from host 10 (10.0.0.1).
EXPLANATION:
An error occurred receiving data from 10 (10.0.0.1) over TCP/IP. This may
be due to a communications failure.
Code Used:
package com.company.mq;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;
import com.ibm.mq.MQC;
import com.ibm.mq.MQEnvironment;
import com.ibm.mq.MQException;
import com.ibm.mq.MQGetMessageOptions;
import com.ibm.mq.MQMessage;
import com.ibm.mq.MQPutMessageOptions;
import com.ibm.mq.MQQueue;
import com.ibm.mq.MQQueueManager;
public class MQConnection {
private static final String CORR_ID = "CORRELID";
String qMgrStr = "";
String hostName = "hostname";
String password ="xxxx";
String userName ="username";
String putqueueName = "putqueuename";
String getqueuename = "getqueuename ";
String channel = "channel";
String replyToQueue = "replyToQueue";
String replyToQueueManager = "";
static String content = "";
int port =10000;
MQQueue readQueue = null;
MQQueue writeQueue = null;
MQQueueManager qManager;
#SuppressWarnings("unchecked")
public void init(){
MQEnvironment.hostname =hostName;
MQEnvironment.channel = channel;
MQEnvironment.port = port;
MQEnvironment.userID = userName;
MQEnvironment.password = password;
MQEnvironment.properties.put(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_CLIENT);
try {
qManager = new MQQueueManager("");
System.out.println("qManager====>"+qManager);
}catch(Exception e){
e.printStackTrace();
}
try {
System.out.println("qManager==> hhh"+qManager);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public String putAndGetMessage() throws InterruptedException, IOException{
int openOptions = MQC.MQOO_OUTPUT | MQC.MQPMO_SET_ALL_CONTEXT | MQC.MQOO_FAIL_IF_QUIESCING;
String msgString = content.toString();
System.out.println("msgString=="+msgString);
int expiryTime =60000;
MQMessage getmessage = null;
int waitInterval =4000;
try {
System.out.println("qManager Desc==>"+qManager.getDescription());
writeQueue =openWriteQueue(qManager,putqueueName);
MQMessage message = myPut(writeQueue,msgString,expiryTime,getqueuename);
// qManager.accessQueue(putqueueName, openOptions,null,null,null);
readQueue =openReadQueue(qManager,getqueuename);
getmessage =mqGet(readQueue,waitInterval,message.messageId);
/*MQMessage msg = new MQMessage();
msg.messageType = MQC.MQMT_REQUEST;
msg.format = "MQSTR";
// msg.characterSet = 500;
msg.persistence = MQC.MQPER_NOT_PERSISTENT;
msg.correlationId = CORR_ID.getBytes();
// msg.messageId = CORR_ID.getBytes();
msg.expiry= 10000;*/
/*System.out.println("before");
Thread.sleep(10000);
System.out.println("after");*/
/*MQGetMessageOptions gmo = new MQGetMessageOptions();
int openOptions1 = MQC.MQGMO_WAIT| MQC.MQGMO_CONVERT| MQC.MQGMO_FAIL_IF_QUIESCING;
System.out.println("in getqManager==>"+qManager);
readQueue = qManager.accessQueue(getqueuename, openOptions1);
System.out.println("deafaultQueue======>"+readQueue);
readQueue.get(getmessage,gmo);
System.out.println(getmessage.readInt());
String retriveMsg = getmessage.readUTF();
System.out.println("read===>"+retriveMsg);*/
} catch(MQException e){
e.printStackTrace();
}
return getmessage.readString(getmessage.getMessageLength());
}
private MQMessage mqGet(MQQueue readQueue2, int waitInterval,
byte[] corrID) throws MQException {
MQMessage responseMessage = new MQMessage();
responseMessage.correlationId =corrID;
MQGetMessageOptions gmo = new MQGetMessageOptions();
gmo.options =MQC.MQGMO_WAIT| MQC.MQGMO_CONVERT| MQC.MQGMO_FAIL_IF_QUIESCING;
gmo.matchOptions = MQC.MQMO_MATCH_CORREL_ID;
gmo.waitInterval = waitInterval;
// TODO Auto-generated method stub
readQueue2.get(responseMessage,gmo);
return responseMessage;
}
private MQQueue openReadQueue(MQQueueManager manager, String getqueuename2) throws MQException {
// TODO Auto-generated method stub
return openQueue(manager,getqueuename2,MQC.MQOO_INPUT_SHARED | MQC.MQOO_INQUIRE |MQC.MQOO_FAIL_IF_QUIESCING);
}
private MQMessage myPut(MQQueue writeQueue2, String msgString,
int expiryTime, String getqueuename2) {
// TODO Auto-generated method stub
MQPutMessageOptions mpo =new MQPutMessageOptions();
mpo.options = MQC.MQPMO_NEW_MSG_ID | MQC.MQMO_MATCH_CORREL_ID;
MQMessage putmessage = new MQMessage();
putmessage.format = MQC.MQFMT_STRING;
putmessage.messageFlags = MQC.MQMT_REQUEST;
putmessage.replyToQueueName =replyToQueue;
putmessage.replyToQueueManagerName = qMgrStr;
putmessage.userId="userId";
putmessage.expiry =expiryTime;
try {
putmessage.write(msgString.getBytes());
try {
writeQueue2.put(putmessage,mpo);
} catch (MQException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return putmessage;
}
private MQQueue openWriteQueue(MQQueueManager manager, String queueName) throws MQException{
// TODO Auto-generated method stub
return openQueue(manager,queueName,MQC.MQOO_OUTPUT | MQC.MQPMO_SET_ALL_CONTEXT | MQC.MQOO_FAIL_IF_QUIESCING);
}
private MQQueue openQueue(MQQueueManager manager, String queueName, int options) throws MQException{
// TODO Auto-generated method stub
return manager.accessQueue(queueName, options,null,null,null);
}
/**
* #param args
* #throws IOException
* #throws InterruptedException
*/
public static void main(String[] args) throws IOException, InterruptedException {
// TODO Auto-generated method stub
MQConnection conn = new MQConnection();
DataInputStream dis = new DataInputStream ( new FileInputStream ("c://request//Request.xml"));
byte[] datainBytes = new byte[dis.available()];
dis.readFully(datainBytes);
dis.close();
content = new String(datainBytes, 0, datainBytes.length);
//System.out.println("content===>"+content);
conn.init();
System.out.println("connected");
conn.putAndGetMessage();
}
}
The application appears to be a class which encapsulates the MQ I/O. On instantiation, the init routine constructs the class and attempts to connect to the queue manager. There are a few problems with the code that I can see. Also, and I suspect I know why the code fails but there is no diagnostic information provided in the question so I can only guess. I'll describe the problems first, then which diagnostic info I'd normally expect.
Code issues
The code provides a user ID and password. Unless this is a v8.0 client talking to a v8.0 queue manager, or a client that uses an exit to talk to MQ over a TLS channel, the password is not being checked and not needed. Even worse, if the channel is not TLS and encrypted, the ID and password are being transmitted in the clear over the network. Take the password out. Use the ID only if the ID presented by the app needs to be overridden in the connection request.
The code is not printing the linked exception. A JMS exception is a multi-level data structure in which the top level is the exception as JMS understands it and the lower level exception is the one the transport provider understands. Many transport providers, especially those written in pure Java, use only the top level of the data structure and do not supply a linked exception. However, as a developer you must not assume that this will never be the case.
There is no valid reason for a JMS developer to ever fail to print the linked exception.
When I was managing the MQ Admin team at a large bank, my policy was that nothing went to Production if it did not follow these rules:
When encountering a JMS exception, the code must print the linked exception.
If there is no exception linked to a JMS Exception, the code must print the string "No linked exception found" so that we know that it has at least looked for one.
The code opens the queue with the MQC.MQPMO_SET_ALL_CONTEXT option. This level of privilege is not normally granted to non-admin users. The code explicitly specifies an ID which suggests it is not running with admin privileges. For these reasons, I suspect that you are getting a 2035 error, which of course you do not see because the code fails to print the linked exception.
Missing diagnostics
MQ behaves differently from version to version. Over the years the Java/JMS classes have been repackaged, refactored, and upgraded to JMS 1.1, then to JMS 2.0. Diagnostic questions, whether posted here or sent to your MQ Admin tean for a Production outage, should indicate the versions of MQ client and MQ server in use. The output of dspmqver -a on the client node and the server node are always helpful.
As mentioned previously, the linked exception is not being printed. Without it the stack trace is probably worthless, so for once I'm not that disappointed no stack trace was provided. However, update the code to print the linked exception and include a stack trace in the future.
Both the client and the server produce error logs. In addition to the queue manager's error log, there are global error logs on the server for things that happen before the queue manager has been identified or for commands which operate on the global MQ configuration. No error log information from any of these sources was provided in this case. Why not?
The server also produces event messages. These are normally consumed by a monitoring agent but may be enabled by administrators and reviewed to determine the problem. In the absence of error log messages, event messages can be very helpful. I would not expect them in this case but mention it here for completeness.
FDC files are produced by the queue manager and stored in the same directory as the global error logs. These provide much more detailed information than the error log entries but are not always produced. Usually a problem diagnosis request would mention either that there were no FDC files produced, or else that they were and provide the header block from them.
Resources
Please see:
The MQ Knowledge Center, if you have not already found it.
In particular, the section on troubleshooting,
and the section on linked exceptions. (Although these are not specific to MQ, IBM has at least provided some sample code you can copy and paste. Be sure to paste as plain text and correct any curly quotes.)
The MQ SupportPacs page,
...and in particular MS0T is the latest MQ Explorer (which works with back-level QMgrs) and MS0P is a set of plug-ins that allow Explorer to parse the event messages, among many other things.
IBM's MQDev community. Though this is great for finding articles and reference materials, the forums are mediocre.
For a community, I much prefer the Vienna MQ list server or the forum at MQSeries.net. Both are thriving communities of developers, admins and IBMers.
Keep posting here in the websphere-mq tag, of course. Neither of the communities above has a well-developed FAQ for MQ and Stack Overflow provides that function. There are several MQ old-timers and IBMers curating the Stack Overflow MQ tag.
If you can manage the funding and travel, attend the MQ Tech Conference. IBM used to have the Transaction and Messaging conference but combined those with the rest of WebSphere to form IMPACT. Last year it combined several conferences, including IMPACT, into Interconnect. The MQ Tech conference is all MQ, all week, and insanely inexpensive. Since IBM outsourced their MQ curriculum and training, classroom training is a less viable option, and the conferences cover material not available in the classroom training.
Stick with it and good luck!
Full disclosure: I am one of the founders, and my MQ consulting firm is a sponsor, of the MQ Tech conference. However, it had almost as many MQ sessions on it's first day last year as Interconnect had all week so I do not see a conflict of interest in recommending it.
Related
I'm writing a main class that will create a few clients and test them subscribing and publishing. I'd like to display information of the clients connection, like the data & time connected, clientId, clientIP used to connect, whether they connected gracefully or not. I'm new to using tools like Logger so I'm not sure how I would do this. I left a link to the HiveMQ community edition (broker) and the client. I'd like to display this information in my main class in the HiveMQ client project but there a log file in the community edition called event.log which contains exactly the kind of information I want to display. I left an image below.
HiveMQ:
https://github.com/hivemq/hivemq-community-edition
https://github.com/hivemq/hivemq-mqtt-client
There is an event.log file in hivemq-community-edition that has the kind of information I'd like to display. It was generated when I build the project as a Gradle project so it won't be found unless you imported into Eclipse and built in with Gradle so I left a screenshot of what it looks like.
Code in my Main class in HiveMQ Client:
package com.main;
import java.util.UUID;
import com.hivemq.client.mqtt.MqttGlobalPublishFilter;
import com.hivemq.client.mqtt.datatypes.MqttQos;
import com.hivemq.client.mqtt.mqtt5.Mqtt5BlockingClient;
import com.hivemq.client.mqtt.mqtt5.Mqtt5BlockingClient.Mqtt5Publishes;
import com.hivemq.client.mqtt.mqtt5.Mqtt5Client;
import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish;
import java.util.logging.Logger;
import java.util.NoSuchElementException;
import java.util.logging.Level;
import java.util.concurrent.TimeUnit;
public class Main {
private static final Logger LOGGER = Logger.getLogger(Main.class.getName()); // Creates a logger instance
public static void main(String[] args) {
Mqtt5BlockingClient client1 = Mqtt5Client.builder()
.identifier(UUID.randomUUID().toString()) // the unique identifier of the MQTT client. The ID is randomly generated between
.serverHost("localhost") // the host name or IP address of the MQTT server. Kept it 0.0.0.0 for testing. localhost is default if not specified.
.serverPort(1883) // specifies the port of the server
.buildBlocking(); // creates the client builder
client1.connect(); // connects the client
System.out.println("Client1 Connected");
System.out.println(client1.toString());
String testmessage = "How is it going!";
byte[] messagebytesend = testmessage.getBytes(); // stores a message as a byte array to be used in the payload
try {
Mqtt5Publishes publishes = client1.publishes(MqttGlobalPublishFilter.ALL); // creates a "publishes" instance thats used to queue incoming messages
client1.subscribeWith() // creates a subscription
.topicFilter("test1/#") // filters to receive messages only on this topic (# = Multilevel wild card, + = single level wild card)
.qos(MqttQos.AT_LEAST_ONCE) // Sets the QoS to 2 (At least once)
.send();
System.out.println("The client1 has subscribed");
client1.publishWith() // publishes the message to the subscribed topic
.topic("test/pancakes/topic") // publishes to the specified topic
.qos(MqttQos.AT_LEAST_ONCE)
.payload(messagebytesend) // the contents of the message
.send();
System.out.println("The client1 has published");
Mqtt5Publish receivedMessage = publishes.receive(5,TimeUnit.SECONDS).get(); // receives the message using the "publishes" instance waiting up to 5 seconds // .get() returns the object if available or throws a NoSuchElementException
byte[] tempdata = receivedMessage.getPayloadAsBytes(); // converts the "Optional" type message to a byte array
System.out.println();
String getdata = new String(tempdata); // converts the byte array to a String
System.out.println(getdata);
}
catch (InterruptedException e) { // Catches interruptions in the thread
LOGGER.log(Level.SEVERE, "The thread was interrupted while waiting for a message to be received", e);
}
catch (NoSuchElementException e){
System.out.println("There are no received messages"); // Handles when a publish instance has no messages
}
client1.disconnect();
System.out.println("Client1 Disconnected");
}
}
You can obtain information about the client with the method getConfig e.g.
Mqtt5ClientConfig config = client.getConfig();
config.getClientIdentifier();
To get the information of the current connection use getConnectionConfig e.g.
Optional<Mqtt5ClientConnectionConfig> connectionConfig = config.getConnectionConfig();
if (connectionConfig.isPresent()) {
MqttClientTransportConfig transportConfig = connectionConfig.get().getTransportConfig();
}
You can also use listeners which are notified when the client is connected or disconnected e.g.
Mqtt5Client.builder()
.addConnectedListener(context -> System.out.println("connected"))
.addDisconnectedListener(context -> System.out.println("disconnected"))
...
IBM Notes 9
Vacation for 2 weeks
All incoming mail needs to be forwarded automatically to a colleague.
All incoming mail needs to also make it my inbox to be reviewed and followed up on when I return.
Here is what I found so far. Please explain steps if possible. I have no experience with Java and very limited experience with C over 5 years ago.
import lotus.domino.*;
import java.util.Vector;
public class JavaAgent extends AgentBase {
public void NotesMain() {
try {
Session session = getSession();
AgentContext agentContext = session.getAgentContext();
// (Your code goes here)
Database db = agentContext.getCurrentDatabase();
DocumentCollection dc =
agentContext.getUnprocessedDocuments();
Document reply;
Vector sendTo;
Document doc = dc.getFirstDocument();
while (doc != null) {
sendTo = doc.getAuthors();
if (!doc.isSentByAgent()) {
reply = doc.createReplyMessage(false);
reply.replaceItemValue
("Subject", "Re: " +
doc.getItemValueString("Subject"));
reply.replaceItemValue(
"Body", "On vacation until 8/15\n");
reply.send(sendTo);
}
doc = dc.getNextDocument(doc);
}
} catch(Exception e) {
e.printStackTrace();
}
}
}
The last time I was gone the admin set up forwarding but it skipped my inbox entirely. It got redirected to my colleague before hitting my inbox. I am not sure how he did this. I have found the code for setting up an autoreply to sender with a canned message about being on vacation. I want to edit this code to instead send the subject and body of the message to another recipient.
I expect to have incoming messages arrive in my inbox, my colleague's inbox, and he can reply to the original sender as well.
simply set up a mail rule (Tools - Rules). You can turn it off upon your return.
Hi Below is a sample code I've written:
import com.siebel.data.*;
import com.siebel.data.SiebelException;
public class DataBeanDemo
{
private SiebelDataBean m_dataBean = null;
private SiebelBusObject m_busObject = null;
private SiebelBusComp m_busComp = null;
public static void main(String[] args)
{
DataBeanDemo demo = new DataBeanDemo();
}
public DataBeanDemo()
{
try
{
m_dataBean = new SiebelDataBean();
m_dataBean.login("Siebel://devServerXYZ:7777/XYZ/
ecommunication_enu", ROSADMIN, ROSADMIN, "enu");
System.out.println("Connected");
m_busObject = m_dataBean.getBusObject("Opportunity");
m_busComp = m_busObject.getBusComp("Opportunity");
m_dataBean.logoff();
}
catch (SiebelException e)
{
System.out.println(e.getErrorMessage());
}
}
}
This code executes without issues, but gets stuck at m_dataBean.login(). And never returns.
What could be the issue?
If I try to change connect string (even port name, from 7777 to any other number like 2320, 2321) then I get error could not open a session in 4 attempts SBL-JCA-00200.
3 things to verify
Parameters in the connect string. Gtway server name, OM comp name, port number etc. (Username/Password error is showed immediately but rest others throw generic errors or hung forever)
(This is something that's specific to Siebel) Ensure that Java subsystem profile has classpath pointing to siebel.jar and siebelJI_lang.jar files
Siebel Server is up and running.
If LDAP is true, then such logins cannot be used using Databeans.
In my case it was 1 & 2, that was causing issues. By the way Comp name is case sensitive.
My question is that whats the best way to keep track of the exceptions for the administrator of the application. (Notify administrator of the thrown exceptions for maintenance purposes).
To users of the system, I believe should catch the exceptions and show an appropriate error message.
To admin of the system, I suppose, best method is to have a messaging system to send details of each exception as a message to the receiver. Once receiver received a new error message persists it in the database or pings the admin an email with details of the exception.
try{
....
}
catch(Exception e){
//what to do here? how to notify admin?
}
I'd suggest using log4j, configured with an SMTPAppender listening to fatal logs. Then, just log a fatal level message (containing any useful information you can get) for any unhandled exception reaching your global try/catch block.
See also : What is the proper way to configure SMTPAppender in log4j?
Enterprise solution:
Use SL4J and save all messages to your logs.
Use MDC to add tags to your log messages. Have these tags describe who should be notified and the nature of the error:
2014-05-24 [SystemCAD][NOTIFY=ADMIN], [ACCOUNTID=123], [SEVERITY=SEVERE], [MESSAGE="Cannot contact Google.com"]
2014-05-24 [SystemCAD][NOTIFY=USER], [ACCOUNTID=123], [SEVERITY=SEVERE], [MESSAGE="Could not save document to Google. Support has been notified."]
Get Splunk or some product similar to index all your logs for easy searching and to create events which can be used to notify your admins. Use PagerDutty to notify your admins and create escalation, avoid duplicates, create triggers, etc.
First, do not try to solve the notification problem in the application itself.
The recommended approach is to catch the exception at an appropriate point in the application and generate a log event that captures the details (including the exception) of the failure. The primary logging should be done using a standard logging system. There are a number of viable options (e.g. java.util.logging, log4j, logback, log4j2, slf4j), each with pro's and con's, but the most important thing is to not attempt to "roll your own".
That's the easy part.
The hard part is figuring out how to get the notification from the logging system to the admin in a way that is appropriate. There are many things that need to be considered:
The admin does not be woken up at 2am by a page reporting an over-temperature in the office water cooler.
The admin does not want 50 SMS message all reporting the same problem. The system needs to be able to filter out duplicates.
The admin needs to be able to tell the system to "shut up" about a certain problem / issue.
The system needs to recognize that certain events are more important than others, and that business hours versus after hours affects prioritization.
What is the most appropriate way to notify the admin? Email? SMS? Pager?
Escalation - what if the primary (on-call) admin does not respond to the notification?
The system also needs to be integrated with other monitoring; e.g. checking service availability, network connectivity, file system levels, CPU / load average measures, checking that important events DO happen.
All of this needs to be configurable, independent of the application that generated the event in the first place.
Ideally, you need integration with operational issue tracking system ... to help the admin relate the event to previous problems, etc.
This is a really big problem space. Fortunately, there are products out there that do this kind of thing. Too many to list here.
(IMO, it doesn't make sense to recommend a solution for you. We don't know your organization's requirements. This is something that needs to be sorted out in conjunction with operational staff & management.)
I have done notification on exception in my application using spring AOP.
For example
#Aspect
public class ExceptionAspect {
#AfterThrowing(
pointcut = "execution(* com.suren.customer.bo.CustomerBo.addCustomerThrowException(..))",
throwing= "error")
public void logAfterThrowing(JoinPoint joinPoint, Throwable error) {
// Notify admin in email
sendEmail(joinPoint,error);
}
}
Common AspectJ annotations :
#Before – Run before the method execution
#After – Run after the method returned a result
#AfterReturning – Run after the method returned a result, intercept the returned result as well.
#AfterThrowing – Run after the method throws an exception
#Around – Run around the method execution, combine all three advices above.
When you design an application you need to consider two types of exceptions
User defined business exception
Unexpected system exception
User defined exceptions
User defined exceptions are used to pass negative conditions from one layer to another (service to web). For example in a banking application, if there is no balance in an account and if you try to withdraw money, WithdrawService might throw NoBalanceException. The web layer would catch this exception and display appropriate message to the user.
These type of exceptions are of no interest to the administrators and no alert is required. You may simply log it as info.
Unexpected system exception
Unexpected system exceptions are exceptions like database connectivity or JMS conncetivity or NullPointException or invalid message received from external system. Basically any unexpected (non-business) exceptions are classified as system exceptions.
According to Joshua Bloch in Effective Java, it is advisable not to catch system exception as you might do more harm than good. Instead allow it to propagate to the highest level (web layer).
In my applications, I provide a global exception handler (supported by Spring / Struts 2) on the web layer and send a detailed email to the ops team including the exception stack trace and redirect the request to a standard error page which says something like "Unexpected internal error occurred. Please try again".
Using this option is more secured as it will not expose the ugly exception stack trace to the user in any situation.
Struts2 reference:
http://struts.apache.org/release/2.3.x/docs/exception-handling.html
Consider using standard logging (like log4j) and using appender suited for you - either SMTP mentioned before, or custom one. There exists solutions called logging servers - they provide high flexibility in terms of notifications, filtering, storing, processing etc. Good place to start reading and investigating are Scribe and Flume. A great discussion on this subject may be found here.
There are also some cloud solutions available, from automated ones like Sentry through LogDigger (your own installation) to more low-level setups like Amazon SQS.
You should use a logging facility to log every exception in a file system so if Admin want they can view it through file-system.
ErrorUtil
public class ErrorLogUtil {
public static File createErrorFile(String fileName, String productName,
String regionName) {
File fileErrorLogs = new File("Error Logs");
if (!fileErrorLogs.isDirectory()) {
fileErrorLogs.mkdir();
}
File fileProductName = new File(fileErrorLogs, productName);
if (!fileProductName.isDirectory()) {
fileProductName.mkdir();
}
File fileDate = null;
if (regionName != null && regionName.trim().length() != 0) {
File fileRegionName = new File(fileProductName, regionName);
if (!fileRegionName.isDirectory()) {
fileRegionName.mkdir();
}
fileDate = new File(fileRegionName, new SimpleDateFormat(
"dd-MM-yyyy").format(new Date()));
if (!fileDate.isDirectory()) {
fileDate.mkdir();
}
} else {
fileDate = new File(fileProductName, new SimpleDateFormat(
"dd-MM-yyyy").format(new Date()));
if (!fileDate.isDirectory()) {
fileDate.mkdir();
}
}
File errorFile = new File(fileDate, fileName + "-errors.txt");
try {
if (!errorFile.exists()) {
errorFile.createNewFile();
System.out.println("New Error File created=>"+errorFile.getAbsolutePath());
}
} catch (IOException e) {
e.printStackTrace();
}
return errorFile;
}
public static void writeError(File errorFile, String error) {
try {
FileOutputStream fileOutputStream = new FileOutputStream(errorFile,
true);
DataOutputStream out = new DataOutputStream(fileOutputStream);
BufferedWriter bufferedWriter = new BufferedWriter(
new OutputStreamWriter(out));
bufferedWriter.append((new Date())+" - "+error);
bufferedWriter.newLine();
bufferedWriter.flush();
bufferedWriter.close();
fileOutputStream.flush();
fileOutputStream.close();
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void printStackTrace(File errorFile, String message, Throwable error) {
try {
FileOutputStream fileOutputStream = new FileOutputStream(errorFile,
true);
DataOutputStream out = new DataOutputStream(fileOutputStream);
PrintWriter bufferedWriter = new PrintWriter(
new BufferedWriter(new OutputStreamWriter(out)));
bufferedWriter.println(new Date() + " : "+ message);
error.printStackTrace(bufferedWriter);
bufferedWriter.println();
bufferedWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Sending mail will not be good because it may fill Admin's mail box but if you really need this you can create a MailUtil and send emails to the user or keep it in a log.
MailUtil
public class MailUtil {
public static void sendEmail(String messageString, String subject, Properties props) {
try {
Session mailSession = null;
final String userName = props.getProperty("mail.from");
final String password = props.getProperty("mail.from.password");
mailSession = Session.getInstance(props, new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(userName, password);
}
});
Transport transport = mailSession.getTransport();
MimeMessage message = new MimeMessage(mailSession);
message.setSubject(subject);
message.setFrom(new InternetAddress(props.getProperty("mail.from")));
String[] to = props.getProperty("mail.to").split(",");
for (String email : to) {
message.addRecipient(Message.RecipientType.TO, new InternetAddress(email));
}
String body = messageString;
message.setContent(body, "text/html");
transport.connect();
transport.sendMessage(message, message.getRecipients(Message.RecipientType.TO));
transport.close();
} catch (Exception exception) {
exception.printStackTrace();
}
}
public static void sendEmail(String subject, String messageString) {
try {
Session mailSession = null;
Properties props=new Properties();
FileInputStream fileInputStream = new FileInputStream(new File("mail-config.properties"));
props.load(fileInputStream);
fileInputStream.close();
final String fromUsername = props.getProperty("mail.from");
final String fromPassword = props.getProperty("mail.from.password");
mailSession = Session.getInstance(props, new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(fromUsername, fromPassword);
}
});
Transport transport = mailSession.getTransport();
MimeMessage message = new MimeMessage(mailSession);
message.setSubject(subject);
message.setFrom(new InternetAddress(fromUsername));
String[] to = props.getProperty("mail.to").split(",");
for (String email : to) {
message.addRecipient(Message.RecipientType.TO, new InternetAddress(email));
}
String body = messageString;
message.setContent(body, "text/html");
transport.connect();
transport.sendMessage(message, message.getRecipients(Message.RecipientType.TO));
transport.close();
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
You should use a property to manage if mail is required or not so in future you can stop mails by just changing the property file.
you can create exception log table. There, Write a code to insert exception with "Pending" status into database whatever exception raised in application.
Create a cron job (linux) or quartz scheduler that will fired in certain period and send mail of "pending" status exception with predefined format to admin user.
Update database entry with "sent" status so it will not send again.
In code, To save exception create super class,i.e.
class UserDao extends CommonDao
{
try
{
}catch(Exception e)
{
saveException(e);
}
}
class CommonDao
{
public void saveException(Exception e)
{
//write code to insert data into database
}
}
For me is not a good idea to put that behavior directly in the code of the application. It is clear that simply call to a function that sends an email in the catch clause it is easy, fast and direct. If you haven't so much time go for it.
But then you will realize that will produce some not expected collateral effects you will need to
Control the performance on exception parsing
Control what exceptions are interesting to notify and what not
Control not send lot of emails because a bug in the application producing exceptions constantly.
For that I prefer to use http://logstash.net/ That allows to put all your logs in a common noSQL database, and then you can use logstash to make dashboards or even create your own applications to send well designed reports about specific events. It require a bit more work at the beginning but after that I'm sure you will have more control about what is important to see in the logs and what not.
What are the possible ways to send and receive sms from Java application?
How?
(Disclaimer: I work at Twilio)
Twilio offers a Java SDK for sending SMS via the Twilio REST API.
if all you want is simple notifications, many carriers support SMS via email; see SMS through E-Mail
There is an API called SMSLib, it's really awesome.
http://smslib.org/
Now you have a lot of Saas providers that can give you this service using their APIs
Ex: mailchimp, esendex, Twilio, ...
The best SMS API I've seen in Java is JSMPP. It is powerful, easy to use, and I used it myself for an enterprise-level application (sending over 20K SMS messages daily).
This API created to reduce the verbosity of the existing SMPP API.
It's very simple and easy to use because it hides the complexity of
the low level protocol communication such as automatically enquire
link request-response.
https://code.google.com/p/jsmpp/
I've tried some other APIs such as Ozeki, but most of them either is commercial or has limitation in its throughput (i.e can't send more than 3 SMS messages in a second, for example).
You Can Do this With A GSM Modem and Java Communications Api [Tried And Tested]
First You Need TO Set Java Comm Api
This Article Describes In Detail How to Set Up Communication Api
Next You Need A GSM Modem (preferably sim900 Module )
Java JDK latest version preferable
AT Command Guide
Code
package sample;
import java.io.*;
import java.util.*;
import gnu.io.*;
import java.io.*;
import org.apache.log4j.chainsaw.Main;
import sun.audio.*;
public class GSMConnect implements SerialPortEventListener,
CommPortOwnershipListener {
private static String comPort = "COM6"; // This COM Port must be connect with GSM Modem or your mobile phone
private String messageString = "";
private CommPortIdentifier portId = null;
private Enumeration portList;
private InputStream inputStream = null;
private OutputStream outputStream = null;
private SerialPort serialPort;
String readBufferTrial = "";
/** Creates a new instance of GSMConnect */
public GSMConnect(String comm) {
this.comPort = comm;
}
public boolean init() {
portList = CommPortIdentifier.getPortIdentifiers();
while (portList.hasMoreElements()) {
portId = (CommPortIdentifier) portList.nextElement();
if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
if (portId.getName().equals(comPort)) {
System.out.println("Got PortName");
return true;
}
}
}
return false;
}
public void checkStatus() {
send("AT+CREG?\r\n");
}
public void send(String cmd) {
try {
outputStream.write(cmd.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
public void sendMessage(String phoneNumber, String message) {
char quotes ='"';
send("AT+CMGS="+quotes + phoneNumber +quotes+ "\r\n");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// send("AT+CMGS=\""+ phoneNumber +"\"\r\n");
send(message + '\032');
System.out.println("Message Sent");
}
public void hangup() {
send("ATH\r\n");
}
public void connect() throws NullPointerException {
if (portId != null) {
try {
portId.addPortOwnershipListener(this);
serialPort = (SerialPort) portId.open("MobileGateWay", 2000);
serialPort.setSerialPortParams(115200,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);
} catch (PortInUseException | UnsupportedCommOperationException e) {
e.printStackTrace();
}
try {
inputStream = serialPort.getInputStream();
outputStream = serialPort.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
try {
/** These are the events we want to know about*/
serialPort.addEventListener(this);
serialPort.notifyOnDataAvailable(true);
serialPort.notifyOnRingIndicator(true);
} catch (TooManyListenersException e) {
e.printStackTrace();
}
//Register to home network of sim card
send("ATZ\r\n");
} else {
throw new NullPointerException("COM Port not found!!");
}
}
public void serialEvent(SerialPortEvent serialPortEvent) {
switch (serialPortEvent.getEventType()) {
case SerialPortEvent.BI:
case SerialPortEvent.OE:
case SerialPortEvent.FE:
case SerialPortEvent.PE:
case SerialPortEvent.CD:
case SerialPortEvent.CTS:
case SerialPortEvent.DSR:
case SerialPortEvent.RI:
case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
case SerialPortEvent.DATA_AVAILABLE:
byte[] readBuffer = new byte[2048];
try {
while (inputStream.available() > 0)
{
int numBytes = inputStream.read(readBuffer);
System.out.print(numBytes);
if((readBuffer.toString()).contains("RING")){
System.out.println("Enter Inside if RING Loop");
}
}
System.out.print(new String(readBuffer));
} catch (IOException e) {
}
break;
}
}
public void outCommand(){
System.out.print(readBufferTrial);
}
public void ownershipChange(int type) {
switch (type) {
case CommPortOwnershipListener.PORT_UNOWNED:
System.out.println(portId.getName() + ": PORT_UNOWNED");
break;
case CommPortOwnershipListener.PORT_OWNED:
System.out.println(portId.getName() + ": PORT_OWNED");
break;
case CommPortOwnershipListener.PORT_OWNERSHIP_REQUESTED:
System.out.println(portId.getName() + ": PORT_INUSED");
break;
}
}
public void closePort(){
serialPort.close();
}
public static void main(String args[]) {
GSMConnect gsm = new GSMConnect(comPort);
if (gsm.init()) {
try {
System.out.println("Initialization Success");
gsm.connect();
Thread.sleep(5000);
gsm.checkStatus();
Thread.sleep(5000);
gsm.sendMessage("+91XXXXXXXX", "Trial Success");
Thread.sleep(1000);
gsm.hangup();
Thread.sleep(1000);
gsm.closePort();
gsm.outCommand();
System.exit(1);
} catch (Exception e) {
e.printStackTrace();
}
} else {
System.out.println("Can't init this card");
}
}
}
You can use Nexmo to send SMS as well as receive SMS.
Sending SMS with the Nexmo Java Library is fairly straightforward. After creating a new account, renting a virtual number, and getting your API key & secret you can use the library to send SMS like so:
public class SendSMS {
public static void main(String[] args) throws Exception {
AuthMethod auth = new TokenAuthMethod(API_KEY, API_SECRET);
NexmoClient client = new NexmoClient(auth);
TextMessage message = new TextMessage(FROM_NUMBER, TO_NUMBER, "Hello from Nexmo!");
//There may be more than one response if the SMS sent is more than 160 characters.
SmsSubmissionResult[] responses = client.getSmsClient().submitMessage(message);
for (SmsSubmissionResult response : responses) {
System.out.println(response);
}
}
}
To receive SMS you'll need to set up a server that consumes a webhook. That's fairly simple as well. I recommend checking out our tutorial on receiving SMS with Java.
Disclosure: I work for Nexmo
There are two ways :
First : Use a SMS API Gateway which you need to pay for it , maybe you find some trial even free ones but it's scarce .
Second : To use AT command with a modem GSM connected to your laptop .
that's all
TextMarks gives you access to its shared shortcode to send and receive text messages from your app via their API. Messages come from/to 41411 (instead of e.g. a random phone# and unlike e-mail gateways you have the full 160 chars to work with).
You can also tell people to text in your keyword(s) to 41411 to invoke various functionality in your app. There is a JAVA API client along with several other popular languages and very comprehensive documentation and technical support.
The 14 day free trial can be easily extended for developers who are still testing it out and building their apps.
Check it out here: TextMarks API Info
OMK.smpp. API. it's base on SMPP
and simulator is also available for free
LOGICA SMPP API.
And another option is Kannel a free WAP and SMS gateway.
I suggest a cloud based solution like Twilio. Cloud based solutions are cost-effective, than an in-house solution as the there is no ongoing maintenance, required. SMS through email is not an elegant solution, as you have to get the carrier information from the user and you can never be sure that you can text all mobile numbers.
I am using twilio java api in my web application, to send sms from serverside. within few minutes, you can integrate with your app.
https://www.twilio.com/docs/java/install
Here's an example sending an SMS message from the docs:
import com.twilio.sdk.TwilioRestClient;
import com.twilio.sdk.TwilioRestException;
import com.twilio.sdk.resource.factory.MessageFactory;
import com.twilio.sdk.resource.instance.Message;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import java.util.ArrayList;
import java.util.List;
public class Example {
// Find your Account Sid and Token at twilio.com/user/account
public static final String ACCOUNT_SID = "{{ account_sid }}";
public static final String AUTH_TOKEN = "{{ auth_token }}";
public static void main(String[] args) throws TwilioRestException {
TwilioRestClient client = new TwilioRestClient(ACCOUNT_SID, AUTH_TOKEN);
// Build a filter for the MessageList
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("Body", "Test Twilio message"));
params.add(new BasicNameValuePair("To", "+14159352345"));
params.add(new BasicNameValuePair("From", "+14158141829"));
MessageFactory messageFactory = client.getAccount().getMessageFactory();
Message message = messageFactory.create(params);
System.out.println(message.getSid());
}
}
You can you LOGICA SMPP Java API for sending and Recieving SMS in Java application.
LOGICA SMPP is well proven api in telecom application. Logica API also provide you with signalling capicity on TCP/IP connection.
You can directly integrate with various telecom operator accross the world.
It depends on how you're going to work and who your provider is.
If you work with a sms-gateway company you'll probably work through SMPP protocol (3.4 is still the most common), then have a look on OpenSMPP and jSMPP. These are powerful libs to work with SMPP.
If you're going to work with your own hardware (f.e. a gsm-modem) the easiest way to send messages is through AT commands, they differ depends on the model, so, you should find out what AT commands is supported by your modem. Next, if your modem has an IP and open to connection, you can send commands through java socket
Socket smppSocket = new Socket("YOUR_MODEM_IP", YOUR_MODEM_PORT);
DataOutputStream os = new DataOutputStream(smppSocket.getOutputStream());
DataInputStream is = new DataInputStream(smppSocket.getInputStream());
os.write(some_byte_array[]);
is.readLine();
Otherwise you'll work through a COM port, but the method is the same (sending AT commands), you can find more information how to work with serial ports here.
You can use Twilio for this. But if you are looking for some tricky workaround you can follow the workaround I have mentioned below.
This is not possible for receiving sms. But this is a tricky method you can use to send sms to number of clients. You can use twitter API. We can follow twitter account from our mobile phone with a sms. We just have to send sms to twitter. Imagine we create a twitter account with the user name of #username. Then we can send sms to 40404 as shown below.
follow #username
Then we start to get tweets which are tweeted in that account.
So after we create a twitter account then we can use Twitter API to post tweets from that account. Then all the clients who have follow that account as I mentioned before start to receiving tweets.
You can learn how to post tweets with twitter API from following link.
Twitter API
Before you start developing you have to get permission to use twitter api. You can get access to twitter api from following link.
Twitter Developer Console
This is not the best solution for your problem.But hope this help.
We also love Java in Wavecell, but this question can be answered without language-specific details since we have a REST API which will cover most of your needs:
curl -X "POST" https://api.wavecell.com/sms/v1/amazing_hq/single \
-u amazing:1234512345 \
-H "Content-Type: application/json" \
-d $'{ "source": "AmazingDev", "destination": "+6512345678", "text": "Hello, World!" }'
Look at this questions if you have problems with sending HTTP requests in Java:
HTTP POST using JSON in Java
How can I send json object in http post in java
For specific cases you can also consider using the SMPP API and already mentioned JSMPP library will help with that.
There is Ogham library. The code to send SMS is easy to write (it automatically handles character encoding and message splitting). The real SMS is sent either using SMPP protocol (standard SMS protocol) or through a provider.
You can even test your code locally with a SMPP server to check the result of your SMS before paying for real SMS sending.
package fr.sii.ogham.sample.standard.sms;
import java.util.Properties;
import fr.sii.ogham.core.builder.MessagingBuilder;
import fr.sii.ogham.core.exception.MessagingException;
import fr.sii.ogham.core.service.MessagingService;
import fr.sii.ogham.sms.message.Sms;
public class BasicSample {
public static void main(String[] args) throws MessagingException {
// [PREPARATION] Just do it once at startup of your application
// configure properties (could be stored in a properties file or defined
// in System properties)
Properties properties = new Properties();
properties.setProperty("ogham.sms.smpp.host", "<your server host>"); // <1>
properties.setProperty("ogham.sms.smpp.port", "<your server port>"); // <2>
properties.setProperty("ogham.sms.smpp.system-id", "<your server system ID>"); // <3>
properties.setProperty("ogham.sms.smpp.password", "<your server password>"); // <4>
properties.setProperty("ogham.sms.from.default-value", "<phone number to display for the sender>"); // <5>
// Instantiate the messaging service using default behavior and
// provided properties
MessagingService service = MessagingBuilder.standard() // <6>
.environment()
.properties(properties) // <7>
.and()
.build(); // <8>
// [/PREPARATION]
// [SEND A SMS]
// send the sms using fluent API
service.send(new Sms() // <9>
.message().string("sms content")
.to("+33752962193"));
// [/SEND A SMS]
}
}
There are many other features and samples / spring samples.
You can use AT & T commands for sending sms using GSM modem.