Is this PowerBuilder stats generation code appropriately object-oriented? - java

I am working on refactoring an existing application written in PowerBuilder and Java and which runs on Sybase EA Server (Jaguar). I am building a small framework to wrap around Jaguar API functions that are available in EA Server. One of the classes is to get runtime statistics from EA Server using the Monitoring class.
Without going into too much detail, Monitoring is a class in EA Server API that provides Jaguar Runtime Monitoring statistics (actual classes are in C++; EA Server provides a wrapper for these in Java, so they can be accessed through CORBA).
Below is the simplified version of my class. (I made a superclass which I inherit from for getting stats for components, conn. caches, HTTP etc).
public class JagMonCompStats {
...
public void dumpStats(String type, String entity) {
private String type = "Component";
private String entity = "web_business_rules";
private String[] header = {"Active", "Pooled", "invoke"};
// This has a lot more keys, simplified for this discussion
private static short[] compKeys = {
(short) (MONITOR_COMPONENT_ACTIVE.value),
(short) (MONITOR_COMPONENT_POOLED.value),
(short) (MONITOR_COMPONENT_INVOKE.value)
};
private double[] data = null;
...
/* Call to Jaguar API */
Monitoring jm = MonitoringHelper.narrow(session.create("Jaguar/Monitoring"));
data = jm.monitor(type, entity, keys);
...
printStats(entity, header, data);
...
}
protected void printStats(String entityName, String[] header, double[] data) {
/* print the header and print data in a formatted way */
}
}
The line data = jm.monitor is the call to Jaguar API. It takes the type of the entity, the name of the entity, and the keys of the stats we want. This method returns a double array. I go on to print the header and data in a formatted output.
The program works, but I would like to get experts' opinion on OO design aspect. For one, I want to be able to customize printStats to be able to print in different formats (for e.g., full blown report or a one-liner). Apart from this, I am also thinking of showing the stats on a web page or PowerBuilder screen, in which case printStats may not even be relevant. How would you do this in a real OO way?

Well, it's quite simple. Don't print stats from this class. Return them. And let the caller decide how the returned stats should be displayed.
Now that you can get stats, you can create a OneLinerStatsPrinter, a DetailedStatsPrinter, an HtmlStatsFormatter, or whatever you want.

Related

j2objc - exception when deserialize enum

I am having trouble deserializing objects that contain an enum. The object serializes without complaint, but I get an InvalidObjectException when I deserialize the object. The exception message says that there is "No enum constant com.mypackagname."
I have isolated and reproduced the problem by creating some test code based on the testSerialization() method in SerializationTest.java.
public class SerializationTest {
private static final String TEST_FILE_NAME = "serialization-test.bin";
public enum Gender { MALE, FEMALE }
public void testEnumSerialization() throws IOException, ClassNotFoundException {
Gender gender = Gender.MALE;
// Save the enum to a file.
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(TEST_FILE_NAME));
out.writeObject(gender);
out.close();
// Read back the enum.
ObjectInputStream in = new ObjectInputStream(new FileInputStream(TEST_FILE_NAME));
Gender gender2 = (Gender) in.readObject();
in.close();
}
}
I have discovered that if I add a string value to the enum initialization in the generated Objective C code the deserialization works fine. The resulting initialize method in Obj C looks like this:
+ (void)initialize {
if (self == [SerializationTest_Gender class]) {
JreEnum(SerializationTest_Gender, MALE) = new_SerializationTest_Gender_initWithNSString_withInt_(#"MALE", 0);
JreEnum(SerializationTest_Gender, FEMALE) = new_SerializationTest_Gender_initWithNSString_withInt_(#"FEMALE", 1);
J2OBJC_SET_INITIALIZED(SerializationTest_Gender)
}
}
Note that I added the #"MALE" and #"FEMALE", the default from the j2objc output is #"".
I have two questions. (1) Is this the correct way to enable a round trip serialization/deserialization of enums? (2) If so, is there a way to have j2objc automatically populate the string constants in the enum rather than coding them by hand?
Thanks for any help you can provide.
We probably broke this with a recent change eliminating redundant enum constant name strings. We had the name defined both in the enum's class initializer and in its metadata, plus we had an important request to stop making enum constants easily discovered in app binaries (apparently tech writers have been known to dump early access binaries and run strings on them to get scoops on any new features). Now the constant name is only in the metadata (no redundancy), and if an app builds with --strip-reflection, the enum has no metadata and the name becomes the enum class plus the constant's ordinal. However, serialization support was overlooked since Google apps use protocol buffers instead (faster and less version-sensitive).
Thanks for the excellent test case, which will make it easier to fix. Please file a bug if you want to be notified when this is fixed.

Using Thrift for offline serialisation?

I use Apache Thrift protocol for tablet-server and interlanguage integration, and all is OK few years.
Integration is between languages (C#/C++/PC Java/Dalvik Java) and thrift is probably one of simplest and safest. So I want pack-repack sophisticated data structures (and changed over years) with Thrift library. Lets say in thrift terms kind of OfflineTransport or OfflineProtocol.
Scenario:
I want to make backup solution, for example during internet provider failure process data in offline mode: serialise, store, try to process in few ways. For example sent serialised data by normal email via poor backup connection etc.
Question is: where in Thrift philosophy is best extension point for me?
I understand, only part of online protocol is possible to backup offline, ie real time return of value is not possible, that is OK.
Look for serializer. There are misc. implementations but they all share the same common concept to use a buffer or file / stream as transport medium:
Writing data in C#
E.g. we plan to store the bits into a bytes[] buffer. So one could write:
var trans = new TMemoryBuffer();
var prot = new TCompactProtocol( trans);
var instance = GetMeSomeDataInstanceToSerialize();
instance.Write(prot);
Now we can get a hold of the data:
var data = trans.GetBuffer();
Reading data in C#
Reading works similar, except that you need to know from somewhere what root instance to construct:
var trans = new TMemoryBuffer( serializedBytes);
var prot = new TCompactProtocol( trans);
var instance = new MyCoolClass();
instance.Read(prot);
Additional Tweaks
One solution to the chicken-egg problem during load could be to use a union as an extra serialization container:
union GenericFileDataContainer {
1 : MyCoolClass coolclass;
2 : FooBar foobar
// more to come later
}
By always using this container as the root instance during serialization it is easy to add more classes w/o breaking compatibility and there is no need to know up front what exactly is in a file - you just read it and check what element is set in the union.
There is an RPC framework that uses the standard thrift Protocol named "thrifty", and it is the same effect as using thrift IDL to define the service, that is, thrify can be compatible with code that uses thrift IDL, which is very helpful for cross-platform. And has a ThriftSerializer class in it:
[ThriftStruct]
public class LogEntry
{
[ThriftConstructor]
public LogEntry([ThriftField(1)]String category, [ThriftField(2)]String message)
{
this.Category = category;
this.Message = message;
}
[ThriftField(1)]
public String Category { get; }
[ThriftField(2)]
public String Message { get; }
}
ThriftSerializer s = new ThriftSerializer(ThriftSerializer.SerializeProtocol.Binary);
byte[] s = s.Serialize<LogEntry>();
s.Deserialize<LogEntry>(s);
you can try it:https://github.com/endink/Thrifty

Is this good practice for caching database data on my HTTP servlet?

I'm writing an HTTP servlet (Hosted on Amazon Elastic Beanstalk) that serves as an application server for my Android app. My application will request data from my servlet, which will in turn pull from the database (SimpleDB).
Since my client requests may be frequent, I wanted to implement a cache on my servlet that will cache the requested data so as to cut down on database reads. Currently, I just initialize a "ServerCache" object as a member variable of my servlet. ServerCache contains lists for cached data, and I populate these as I go.
Looks something like this.
public class ServerCache {
/**
* ServerCache is responsible for caching data on the server.
* Create several data structures on the server to cache buy/sell listings as listing objects.
* For now, we will be able to cache the entirety of the database contents.
* -ES
*
* Only one ServerCache should ever be made, at the init() of this server
*/
private List<BuyListing> listbl; //What is the danger of having this public vs. private
private List<SellListing> listsl;
public String BLlastError;
public String SLlastError;
public ServerCache()
{
this.listbl = new ArrayList<BuyListing>();
this.listsl = new ArrayList<SellListing>();
this.BLlastError = "Initialized";
this.SLlastError = "Initialized";
} //Setters and getters ommitted
And it is initialized here
public class HelloWorld extends HttpServlet {
private SimpleDBConnect SDB; // contains functions for accessing database
private ServerCache Cache;
//Various Constants
private static final String BUY_LISTINGS_DOMAIN = "BuyListings";
private static final String SELL_LISTINGS_DOMAIN = "SellListings";
private static final String USER_ID_DOMAIN = "UserIDs";
private static final String MESSAGES_DOMAIN = "Messages";
public HelloWorld() {
super();
SDB = new SimpleDBConnect();
SDB.createConnection();
Cache = new ServerCache();
Cache.setListbl(SDB.getAllBL());
Cache.setListsl(SDB.getAllSL());
updateSDBStatus();
updateServletStatus("Initialized");
updateCacheStatus();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
response.getOutputStream().println("Servlet Works \n SimpleDB Status:" + SDB.dbConnectStatus + "\n \n SDB log: " + this.SDBStatus + "\n \n Servlet log: " + this.ServletStatus
+ "\n \n Buy Cache Status: " + this.BLCacheStatus + "\n \n Sell Cache Status: " + this.SLCacheStatus);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// ... Some code ommitted, the following is a relevant part of how I handle request for data
if (packet.getHeader() == Constants.BL_REQUEST || packet.getHeader() == Constants.SL_REQUEST)
{
MsgStruct temp = new MsgStruct();
if (packet.getHeader() == Constants.BL_REQUEST){
temp.setHeader(Constants.BL_REQUEST);
Type listOfTestObject = new TypeToken<List<BuyListing>>(){}.getType();
String s = gson.toJson(Cache.getListbl(), listOfTestObject);
temp.setPayload(s);
receivedString = gson.toJson(temp);
}
Is there any reason why caching a version of the data on my servlet will be a bad idea? This is just my stab in the dark, as nobody has ever taught me what to do in this case. I'm aware that concurrency is an issue, but I dont think it should matter in this case?
Thanks
Adding a cache into the program will complicate it a little bit, specifically when you want to modify the data. In this case, the database and the cache should always have the same data, no matter what GET or POST requests are received that may or may not write to the database.
A problem you may run into is how to keep the cache in sync with the database. It will be crucial to always update the cache when writing to the database, and make sure that when you fulfill a request with the cache, that you return the same data as is contained in the database. You did say that you're only caching data requested, but if data is ever written back to the database, you will have to check that cached data is also updated.
You mentioned that you'll only instantiate one instance of the class. It might make more sense to follow the singleton pattern for the cache, see the Wikipedia page http://en.wikipedia.org/wiki/Singleton_pattern for more information. Basically, this causes the cache to initialize itself and make sure no other code can make another instance. The constructor will be private, and you would write a getInstance() method to have the cache return the instantiated ServerCache object.
The reason I'm going this route is because there's always a possibility that you will write another servlet that needs to access the database, and it will be difficult to give it cache access without making the cache a singleton (not to mention multithreading issues associated with multiple reads).
Another thing to remember, your cache will take up RAM on the server. Caching trades of RAM usage for access time, and depending on your plan, you may or may not have a lot of that to spare. It's also a real possibility that you'd just replicate your entire database in RAM, defeating its purpose. You would spend a bunch of processing time making sure you update the database but never actually use it. So again, if you see an improvement in responsiveness, I see no problem with it, as long as you manage it well.
To effectively use a cache, you'd have to keep a strict limit on the number of cached objects, getting rid of objects that aren't used much, keeping only the ones that are accessed very frequently. A final point I want to make is that I noticed your cache is using ArrayLists. Those aren't the most efficient data structures for searching unsorted data. A database is made for data storage, so the database most likely has a more efficient storage system anyway, which in your case would make a cache only useful for very small amounts of frequently accessed but seldom modified data.

Why is it that RESTlet takes quite time to print the XML, sometimes

I am implementing REST through RESTlet. This is an amazing framework to build such a restful web service; it is easy to learn, its syntax is compact. However, usually, I found that when somebody/someprogram want to access some resource, it takes time to print/output the XML, I use JaxbRepresentation. Let's see my code:
#Override
#Get
public Representation toXml() throws IOException {
if (this.requireAuthentication) {
if (!this.app.authenticate(getRequest(), getResponse()))
{
return new EmptyRepresentation();
}
}
//check if the representation already tried to be requested before
//and therefore the data has been in cache
Object dataInCache = this.app.getCachedData().get(getURI);
if (dataInCache != null) {
System.out.println("Representing from Cache");
//this is warning. unless we can check that dataInCache is of type T, we can
//get rid of this warning
this.dataToBeRepresented = (T)dataInCache;
} else {
System.out.println("NOT IN CACHE");
this.dataToBeRepresented = whenDataIsNotInCache();
//automatically add data to cache
this.app.getCachedData().put(getURI, this.dataToBeRepresented, cached_duration);
}
//now represent it (if not previously execute the EmptyRepresentation)
JaxbRepresentation<T> jaxb = new JaxbRepresentation<T>(dataToBeRepresented);
jaxb.setFormattedOutput(true);
return jaxb;
}
AS you can see, and you might asked me; yes I am implementing Cache through Kitty-Cache. So, if some XML that is expensive to produce, and really looks like will never change for 7 decades, then I will use cache... I also use it for likely static data. Maximum time limit for a cache is an hour to remain in memory.
Even when I cache the output, sometimes, output are irresponsive, like hang, printed partially, and takes time before it prints the remaining document. The XML document is accessible through browser and also program, it used GET.
What are actually the problem? I humbly would like to know also the answer from RESTlet developer, if possible. Thanks

Java DataStructure for writing 4 pieces of information

I need to extract two pieces of information about two IP addresses and then write those information plus two addresses.
I was thinking of a Set of Pairs for IP addresses, but by which data structure I can write all these information?
Thanks
PcapPacketHandler<String> jPacketHandler = new PcapPacketHandler<String>(){
int totalLength = 0;
public void nextPacket(PcapPacket packet, String user) {
Ip4 ip = new Ip4();
String sIP;
String dIP;
if (packet.hasHeader(ip) == false){
return;
}
totalLength = totalLength+ ip.getPayloadLength();
sIP = org.jnetpcap.packet.format.FormatUtils.ip(ip.source());
dIP = org.jnetpcap.packet.format.FormatUtils.ip(ip.destination());
System.out.println("SIP = "+sIP+" "+"destIP = "+dIP+" "+"Payload Length = "+ip.getPayloadLength());
System.out.println("Total Length = "+totalLength);
}
};
pcap.loop(10, jPacketHandler, "");
pcap.close();
Even though this isn't a Javascript app, you could use JSON as it provides a concise way to read/store multiple pieces of data together. Check out the JSON Java Documentation for details about classes, and to download the related source.
If you're just writing the information you could always use a Hashmap. Unless you know what you're planning to do with the data, it's hard to say what's best.
Just make a custom class (POJO), and depending on how you want to write it make it Serializable. That way you can clearly name your fields (and getters and setters) making your code easier to read (and extend).
some thing like this...
class BigClass { //<br>
private IPAdreess addr1; //<br>
private IPAddress addr2; //<br>
private SomeInfo additionalInfo;//<br>
//implement accessors//<br>
//implement equals, hashCode//<br>
}//<br>
IPAddress, SomeInfo are your user types. In java, InetAddress represents IP address. This may be much more than your custom type.
The selection of suitable data structure of "set" could be decided many factors.. Do you want to retain the order? Do you populate it via multiple threads? How many entries you expect in the set? 100s? A million?
Why not post your code? It may be easier to give feedback with real code..
I don't quite understand what graph you exactly want to plot. What I would do is
Dump all data into an sql database
Run a query to produce input for your chart.
Plot the chart e.g. with JFreeChart or even Excel
I imagine a query along the line
select source_ip, dest_ip, sum(time), sum(sent_bytes) group by source_ip, dest_ip

Categories