JT400 - get messages from Queue - java

I would like to get messages in AS400 from a queue other than a queue from QSYS.LIB. I am using the following code that runs well, only if I use a queue from within QSYS.LIB:
public String getMessagesFromQsysopr(boolean needReply) {
String messageStr = "";
try {
MessageQueue queue = new MessageQueue(this.as400, "/qsys.lib/qsysopr.msgq");
// want only inquiry messages
queue.setSelectMessagesNeedReply(needReply);
queue.setSelectMessagesNoNeedReply(!needReply);
queue.setSelectSendersCopyMessagesNeedReply(needReply);
queue.setListDirection(false);
Enumeration e = queue.getMessages();
while (e.hasMoreElements()) {
QueuedMessage message = (QueuedMessage) e.nextElement();
messageStr += message.getText()+"\n";
}
} catch (Exception e) {
e.printStackTrace();
}
If I replace the /qsys.lib/qsysopr.msgq for any other queue from other lib, like for example "/yaclib.lib/queueName.msgq" I get the following error:
com.ibm.as400.access.IllegalPathNameException: /yaclib.lib/queueName.msgq: Object not in QSYS file system.
at com.ibm.as400.access.QSYSObjectPathName.parse(QSYSObjectPathName.java:599)
at com.ibm.as400.access.QSYSObjectPathName.(QSYSObjectPathName.java:169)
at com.ibm.as400.access.QSYSObjectPathName.(QSYSObjectPathName.java:177)
at com.ibm.as400.access.MessageQueue.(MessageQueue.java:299)
at br.com.operation.AS400Inspector.getMessagesFromYaclib(AS400Inspector.java:225)
at br.com.operation.Main.main(Main.java:43)
Question 1: What am I doing wrong?
Question 2: Is there any way to limit the messages that don't need reply? Like get messages after a specific date or just the last 2 day messages?
Thanks.

#user2338816 is correct.
QSYS is a special library; it actually contains every other library in the system. From a 5250 session, WRKOBJ *ALL *LIB will confirm that every library is the system is in the QSYS library. Interestingly, QSYS itself is contained in QSYS.
When using IFS naming, to refer to a library of YACLIB.LIB, you need to use /QSYS.LIB/YACLIB.LIB
As far as selecting by date, no there's no way to do that. If you look at the java docs the closest you'll find is NEW, NEWEST, OLD, OLDEST

Related

How to set multiple metrics for setDailyMetric method while sending request to Business Profile Performance API?

Following this link getDailyMetricsTimeSeries, I wanna have all the metrics in one request, since I have many locations for every client, it does not seem to be professional if I send one separate request for every single metric.
before in Google My business V4.9 we could use "ALL" to request all available metrics. Unfortunately, this is not working with the new API. Can I get ALL the metrics in ONE single request from Google Business Profile Performance API?
Here is my code in JAVA:
supposing that the variable business_profile_performance is the initialiser global parameters via its Builder and also takes care of authentication.
try {
BusinessProfilePerformance.Locations.GetDailyMetricsTimeSeries metricReport =
business_profile_perfomance.locations().
getDailyMetricsTimeSeries("My locationID" ).
setDailyMetric(dailyMetric).
setDailyRangeStartDateYear(Integer.valueOf("the desired start Year")).
setDailyRangeStartDateMonth(Integer.valueOf(" the desired start Month" )).
setDailyRangeStartDateDay(Integer.valueOf(" the desired start Day ")).
setDailyRangeEndDateYear(Integer.valueOf("the desired End Year" )).
setDailyRangeEndDateMonth(Integer.valueOf(" the desired End Month")).
setDailyRangeEndDateDay(Integer.valueOf("the desired End Day"));
GetDailyMetricsTimeSeriesResponse response = metricReport.execute();
if (!response.isEmpty()) {
System.out.println(dailyMetric + " Response == " + response);
}
} catch (Exception e) {
System.out.println(e);
}
I used a list for my dailyMetric variable, and using a for loop it takes turn as photo below:
If setting dailyMetric to "CALL_CLICKS" works and setting it to "CALL_CLICKS,WEBSITE_CLICKS" does not work, it would seem that the new API does not support that use case anymore.

How do ObjectOutput/ObjectInput Streams work? [duplicate]

This question already has answers here:
What is object serialization?
(15 answers)
Closed 2 years ago.
I'm trying to make a Client/Server chat application using java. I'm pretty new to using sockets to communicate between applications. I've decided to use ObjectInput/ObjectOutput streams to send objects between the client and server.
I'm trying to send user data to the server when the client connects to the socket. Here is the code.
Server:
private void startServer() {
try {
this.server = new ServerSocket(port);
this.socket = server.accept();
ChatUtils.log("Accepted a new connection!");
this.output = new ObjectOutputStream(socket.getOutputStream());
this.input = new ObjectInputStream(socket.getInputStream());
try {
User user = (User) input.readObject();
ChatUtils.log(user.getDisplayName() + " (" + user.getUsername() + ") has connected!");
} catch (ClassNotFoundException e) {
}
} catch (IOException e) {
e.printStackTrace();
}
}
Client:
public void connectToServer(int port) {
try {
server = new Socket("127.0.0.1", port);
this.port = port;
this.objectOutput = new ObjectOutputStream(server.getOutputStream());
System.out.println("Connected to a server on port " + port + "!");
objectOutput.writeObject(user);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Everything works fine, but I'm looking for some clarification as to how the methods ObjectOutputStream#writeObject() and ObjectInputStream#readObject() work.
When I write the line User user = (User) input.readObject();, it reads the object as a User object. Would this only attempt to convert "User" objects that are send from the client's ObjectOutputStream?
As this method is only called once, can I cast the input stream to other objects if I send those objects to the server from the output stream? Ex: String message = (String) input.readObject();.
What would happen if I sent multiple objects to the server from the output stream at once?
4)In example one, I try to read the "user" object. What happens if there are two or more objects waiting to be read? How do I determine which object is which? Ex:
// Client
public void connectToServer() {
String message = "Hello server!"
User user = new User("John Doe", "jdoe123");
output.writeObject(user);
output.writeObject(message);
}
If someone could answer these questions, that'd be great. Thanks so much!
Every time you call .writeObject, java will take the object you specified and will serialize it.
This process is a hacky, not-recommended strategy.
Java will first attempt to break down the object you passed into its constituent parts. It will do this, hopefully, with some assistance from the class definition (the class that the object is, i.e. the one returned by theObjectWritten.getClass(). any class def that implements Serializable claims to be designed for this and gets some additional help, but the mechanism will try with reflection hacks if you don't.
Then, the constituent parts are sent along the wire (that is, take the object, and any fields that are primitives can just be sent; ObjectOutputStream knows how to send an int intrinsically, for example. Any other types are sent by, in turn, asking THAT object's class to do so). For each object, java also sends the so called 'serial version uid', which is a calculated number and changes any time any so-called signature changes anywhere in the class. It's a combination of the class's package, name, which class it extends, which interfaces it implements, and every name and type of every field (and possibly every name, return type, param types, and exception types thrown for every method).
So, now we have a bundle, consisting of:
The name of the class (e.g. com.foo.elliott.User)
The serialversionUID of the class
the actual data in User. If User contained any non-primitive fields, apply this process recursively.
Then this is all sent across the wire.
Then on receipt, the receiving code will take all that and pack it back into a User object. This will fail, unless the receiving end actually has com.foo.elliott.User on the classpath, and that def has the same serial version UID.
In other words, if you ever update this class, the transport fails unless the 'other side' also updates.
You can manually massage this stuff by explicitly declaring the serialVersionUID, but note that e.g. any created fields just end up being blank, even if the constructor ordinarily would ensure they could never be.
You can also fully manually manage all this by overriding some specific 'voodoo' methods (a method with a specific name. Java is ordinarily not structurally typed, but these relics of 25 years in the past, such as psv main and these methods, are the only structurally typed things in all of java).
In addition, the binary format of this data is more or less 'closed', it is not obvious, not easy to decode, and few libraries exist.
So, the upshot is:
It is a finicky, error ridden process.
Updating anything you serialize is a pain in the behind.
You stand no chance of ever reading this wire protocol with any programming language except java.
The format is neither easy to read, nor easy to work with, nor particularly compact.
This leads to the inevitable conclusion: Don't use ObjectOutputStream.
Instead, use other serialization frameworks that weren't designed 25 years ago, such as JSON or XML marshallers like google's GSON or Jackson.
NB: In addition your code is broken. Whenever you make a resource, you must also close it, and as code may exit before you get there, the only solution is a special construct. This is how to do it:
try (OutputStream out = socket.getOutputStream()) { .. do stuff here .. }
note that no matter how code 'escapes' from the braces, be it normally (run to the end of it), or because you return/break/continue out of it, or an exception is thrown, the resource is closed.
This also means assigning resources (anything that implements AutoClosable, like Socket, InputStream, and OutputStream, does so) to fields is broken, unless you make the class itself an AutoClosable, and whomever makes it, does so in one of these try-with blocks.
Finally, don't catch exceptions unless you can actually handle them, and 'printStackTrace' doesn't count. If you have no idea how to handle it, throw it onwards; declare your methods to 'throws IOException'. main can (and should!) generally be declared as throws Exception. If truly you can't, the 'stand in', forget-about-it correct way to handle this, and update your IDE to generate this instead of the rather problematic e.printStackTrace(), is this:
catch (ThingICantHandleException e) {
throw new RuntimeException("unhandled", e);
}
Not doing so means your code continues whilst the process is in an error state, and you don't want that.

Logging a string of big size in java

I'm using logback and I need to log all data queried by clients, to a log file. All the data queried by clients is needed to be logged to the same file. The logging process simply looks like below:
private static final OUTPUTFILELOGGER = Logger.getLogger(...);
String outputString = null;
try {
Map<String, Object> outputMap = doService(); // queries data requested by clients.
.... // do something after business logic..
outputLog = outputMap.toString(); // critical!!
} catch (Throwable e) {
handling exception
} finally {
OUTPUTFILELOGGER.info(outputString);
}
It usually works fine, but sometimes it arises OutOfMemoryError with the call of toString to the outputMap variable when the requested data is too big to make a string.
So I want to make it work in a way of streaming without any problem to performance. And I don't know how to make it effectively and gracefully.
Any idea?
Loop through the map so that you're only working with a small part at a time:
LOGGER.info("Map contains:")
map.forEach( (key, value) -> LOGGER.info("{}: {}", key, value));
(Assumes Java 8 and SLF4J)
However if the map is big enough for the code you've given to generate OOMs, you should probably consider whether it's appropriate to log it in such detail -- or whether your service ought to be capping the response size.

Any Java API in Azure to get existing ServiceBusContract?

I am using the tutorial here for pushing data and consuming, data from Azure Service Bus. When I run the example the second time, I get back an error PUT https://asbtest.servicebus.windows.net/TestQueue?api-version=2012-08 returned a response status of 409 Conflict, which is way of saying you have already a configuration with that name, so do not create it another time. Most probably, this is the guilty code
Configuration config =
ServiceBusConfiguration.configureWithWrapAuthentication(
"HowToSample",
"your_service_bus_owner",
"your_service_bus_key",
".servicebus.windows.net",
"-sb.accesscontrol.windows.net/WRAPv0.9");
ServiceBusContract service = ServiceBusService.create(config);
QueueInfo queueInfo = new QueueInfo("TestQueue");
That is recalling create() is causing the problem, I would guess. But all methods in com.microsoft.windowsazure.services.serviceBus.ServiceBusService from http://dl.windowsazure.com/javadoc/ are only create, and I am unable to find a method like
ServiceBusContract service = A_class_that_finds_existing_bus_contract.find(config);
Am I thinking the wrong way, or is there another way out. Any pointers are appreciated.
EDIT:
I realized my code example for what I was asking was config, not service bus contract. Updated it, to reflect so.
Turns out I was wrong. The create() function in ServiceBusService does not throw any exception, as I gathered from Javadocs. Also, you can create the service bus contracts multiple times, as it being only a connection. The exception arises, when you attempt to create a queue with a name that already exists. That is this line.
String path = "TestQueue";
QueueInfo queueInfo = new QueueInfo(path);
To overcome this, you can go this way.
import com.microsoft.windowsazure.services.serviceBus.Util;
...
...
Iterable<QueueInfo> iqnf = Util.iterateQueues(service);
boolean queue_created = false;
for( QueueInfo qi : iqnf )
{
if( path.toLowerCase().equals( qi.getPath() ))
{
System.out.println(" Queue already exists. Do not create one.");
queue_created = true;
}
}
if ( !queue_created ) {
service.createQueue(queueInfo);
}
Hope, this helps anybody who may be stuck on create conflicts for queue on Azure.
EDIT: Even after I got the path code, my code refused to work. Turns out there is another caveat. Azure makes all queue names in lower case. I have edited the code to use toLower() for this work around.
I upvoted Soham's Question and Answer. I did not know about lowercase though I have not verified it. It did confirm the problem I am having right now as well.
The way #Soham has addressed it is good but not good for large ServicebUs where we may have tons of Queues it's added overhead to iterate it. The only way is to catch the ServiceException which is very generic and ignore that Exception.
Example:
QueueInfo queueInfo = new QueueInfo(queName);
try {
CreateQueueResult qr = service.createQueue(queueInfo);
} catch (ServiceException e) {
//Silently ignore for now.
}
The right way would be for the Azure library to extend the ServiceException and throw "ConcflictException" for e.g. which is present in httpStatusCode of ServiceException but unfortunately it's set to Private.
Since it is not We would have to extend the ServiceException and override the httpStatusCode setter.
Again, not the best way but the library can improve if we list as feedback on their Github issues.
Note: ServiceBus is still in preview phase.

java.lang.ArrayIndexOutOfBoundsException at com.sun.mail.imap.MessageCache.getMessage(MessageCache.java:123)

I am reading emails from emailServer and saving them in database.I am using following code to read messages from folder("INBOX") on email server and retrieve messages corresponding to them but I am getting
"java.lang.ArrayIndexOutOfBoundsException: message number (621) out of bounds (620)
at com.sun.mail.imap.MessageCache.getMessage(MessageCache.java:123)
at com.sun.mail.imap.MessageCache.getMessageBySeqnum(MessageCache.java:153)
at com.sun.mail.imap.IMAPFolder.getMessageBySeqNumber(IMAPFolder.java:2795)
at com.sun.mail.imap.IMAPFolder.getMessagesByUID(IMAPFolder.java:1924)"
I am using javax.mail.1.4.4 , this issue is coming mainly when inbox is getting flooded .
Code used:
folder = store.getFolder("INBOX");
folder.open(Folder.READ_WRITE);
// messageUID is uid of last message I saved in DB
Message messages[] = ((UIDFolder) folder).getMessagesByUID(messageUID + 1, UIDFolder.LASTUID);
I have done some research and found that messagecache is set for a folder as soon as it opens, lets assume it is set as 520( size of the folder). Whereas if any message arrives after message cache is set , then in last message sequence num exceeds total size of message cache and it throws an exception.
Can anybody let me know how to get absolute value of UId of the Last message in a folder or how to acquire a folder lock so that after cache is set , folder does not update the size of the folder.
Interesting problem!
First, I think that this is a bug in javax mail. There should probably be a call to checkRange() in getMessageBySeqNumber(), or just a Math.min() with the vector size.
In any case, the issue is that the the code goes to the server to get the latest message count, but never updates the local messageCache. This means that the messageCache has out of date data compared to the method, yet the method still assumes that it is up to dateā€¦ as you have seen hilarity ensures.
Now, how to avoid it until it is fixed?
Unfortunately, I think that you are stuck with the somewhat horrid workaround of doing something like:
folder = store.getFolder("INBOX");
folder.open(Folder.READ_WRITE);
// messageUID is uid of last message I saved in DB
/* I apologize for all of the kittens that this code is about to kill */
boolean getMessagesWorked = false;
do {
try {
Message messages[] = ((UIDFolder) folder).getMessagesByUID(messageUID + 1, UIDFolder.LASTUID);
getMessagesWorked = true;
} catch (ArrayIndexOutOfBoundsException e) {
/* Doing this should force the internal messagesCache to get updated
* Unfortunately, this is also somewhat racy, depending on just how
* hard the mail folder is being hit */
try {
folder.getMessage(folder.getMessageCount());
} catch (ArrayIndexOutOfBoundsException e) {
/* There really isn't much you can do here, except try again.
* the good news is that this should hardly ever happen!!
* Good in this case is a relative term! */
}
}
} while (! getMessagesWorked);
This is probably this Javamail bug:
https://java.net/projects/javamail/lists/issues/archive/2010-09/message/1

Categories