billroper: (Default)
Well, the calculations are still broken (although I don't think it will take too long to get them fixed once I get the opportunity to get back to them), but the rest of the items for tomorrow's demo look like they'll play successfully.

I am, however, really tired. :)
billroper: (Default)
Turning on basic authentication in the new Java code has caused a great many things to break. I have spent the day patching them and swearing.

I've now run into a serialization problem that I will end up working on some more tonight before going to bed. But I can deal with serialization problems, because they are problems in code that I wrote, not someone else. :)
billroper: (Default)
Oh, boy.

I'm trying to get our Java Server code resuscitated for a demo on Wednesday. This is being more than a bit challenging, as I'm picking up work that one of my Indian colleagues was doing. He's resigned, although he has another two weeks before he leaves.

The problem is that the code that he was working on is not done. I can cope with "not done".

But one of the big pieces he was working on was interfacing with the single-signon authentication code that's in a Java library. And when I attempt to use the class that he set up to handle this, the whole thing collapses with a stack trace that terminates with a ClassCircularityError deep inside the Java library.

You know, that's just not a good thing.

*thud* *thud* *thud*
billroper: (Default)
I've been trying to get the multithreaded version of the calculations running in Java. Well, I finally got something to run today.

It runs more slowly that the single threaded calculation. I have either done something badly wrong or I am being beaten to death by synchronization. To add insult to injury, I'm trying to figure out how to profile the test app in Eclipse, but that isn't working for reasons that I am not yet able to figure out.

*sigh*
billroper: (Default)
With apologies to [livejournal.com profile] jeff_duntemann...

Last night, we had quesadillas for dinner. The girls were initially quite skeptical, but we persuaded Julie to eat a flour tortilla that we had filled with cheese, microwaved, and then folded over. Her reaction: "This is good!" Yes, dear...

The air conditioner in my car has been unwilling to keep up with the heat. On the way back from the baseball game on Saturday, it couldn't get the car cool at all and we finally opened the windows. Today, I took it to Meineke where they vacuumed everything out and recharged the refrigerant. So far, so good.

On the other hand, the leak in the family room ceiling is still there. I've got a very good idea of how the water is coming in now, but the fellow who was going to caulk the area is stubbornly refusing to return my phone calls. You wouldn't think it would be so hard to get this taken care of, but apparently finding someone reliable is harder than it looks. And it rained hard again tonight. *sigh*

The big demo for work went well today. Afterwards, I went through the code and reverted my changes from the weekend and replaced the HashMap in serialization with an IdentityMap as [livejournal.com profile] mdlbear suggested. Happily, the demo code still works after that. :)

And tomorrow the cleaning lady comes. Perhaps she will find the missing car keys.
billroper: (Default)
Thinking some more about yesterday's Java problem:

In almost every case, for an "ID"-type class, two different instances of the ID that contain the same identifiers should return true when passed to the equals() method and should return identical hash code values when the hashCode() method is called. The problem is that the standard equals() and hashCode() methods that are inherited from the Object class will treat these as different objects. If an ID is supposed to uniquely identify some Object (for example, a PersonID that uniquely identifies a Person), only one instance of the ID will work to identify the unique Object if the ID is used as a key in a HashMap or the like, because a different instance of the ID, although conceptually equal, will generate a different hash code and will return false in an equals() comparison.

The solution, then, is to override the equals() and hashCode() methods for the ID classes so that IDs that are conceptually equal will return identical hash code values and will return true in an equals() comparison. This is, in fact, the case by default if the ID is simply a String.

So let's override the hashCode() and equals() methods for the ID classes. Life is good.

Except now there's no way to identify different instances of your ID object. And when you're writing a serialized stream that may contain duplicate references to the same object, you want to know if you've written an object to the stream before, so you can write the object once and restore the duplicate references to the object when reading the serialized stream back into memory. Normally, you could use a HashMap with the object as a key to keep track of this, but now two different instances of the ID will return the same hash code and will return true for equals(), so different instances are interpreted as being the same instance.

It looks like the right answer to this is to define an interface that all of the serializable objects can implement that will, by default, call back to the default object implementations of hashCode() and equals() (let's call them objectHashCode() and objectEquals()); then implement an ObjectHashMap that will call objectHashCode() and objectEquals() instead of hashCode() and equals().

*sigh*

This is an annoying amount of work to do...
billroper: (Default)
I've been trying to beat the bugs out of a Java demo that I'm supposed to do on Monday. This was complicated by socket connections between client and server gleefully timing out whenever I stopped to debug, but one of my compatriots sent me the proper registry settings to fix that problem and debugging became much more tractable.

Unfortunately, the MFC serialization code that I wrote in Java was writing an ID that was causing a problem on the C++ side of the world. Specifically, an ID that was supposed to be unique had shown up on the client side as shared. And when the second attempt was made to delete the same object, well, nothing good at all happened.

I spent a lot of time making sure that all of the IDs and objects were being correctly cloned on the Java side, but no luck.

Ok. Maybe there was a problem in serialization. I traced into the writing code and discovered that I was using a HashMap to store objects so that I could (like the C++ MFC serialization) detect when I was serializing the same object twice and write a reference to it the second time.

But the HashMap calls the hashCode() function for the object on the Java side. And I had overridden the hashCode() function for a couple of the ID objects, because I wanted to make sure that two IDs that contained the same strings would locate the same hash bucket. And this meant that the HashMap in serialization thought they were the same object. So when I encountered the second unique object and wrote it out to the MFC archive, my serialization code wrote a reference to the first object.

Thud. Thud. Thud.

I have now spent the last several hours beating up all of my HashMap code that stored these various IDs so that they now store the keys as Strings. The overriding hashCode() methods have been exterminated.

And maybe this will work now.

*sigh*
billroper: (Default)
Meanwhile, back in the wonderful world of Java:

Java allows you to declare classes inside of classes. Those classes have access to the internal protected members of each other, which is a handy way of circumventing the absence of "friend" classes when you've got a group of related classes that actually need access to those protected members. And it allows me to hide away any of those inner classes that I choose so that other classes in and out of the package can't get access to them.

So what's that good for?

Well, enforcing locking of objects, for one thing.

Let's assume an outer object that other classes will want to use. In this example, we'll call it a Thing. The Thing object itself is immutable so that it cannot be changed, but it contains an inner class, Thing.Mutable, that contains all of the methods that can change a Thing. This will be important in a moment.

The Thing object also contains an inner class, Thing.Lock, that can be used to acquire either a read or a write lock on a Thing. Each Thing has a unique ThingID that can be used to look up a Thing when it is passed to the Thing.Lock class, which will provide access to either a Thing or a Thing.Mutable depending on whether the user requested a read lock or a write lock. Internally, a Thing is stored as a Thing.Mutable, but we'll cast the reference to a Thing before handing it to the user if they've gotten a read lock. (Yes, they could cast the Thing back to a Thing.Mutable, but if they do that, then I cannot help them. :) )

The only way to gain access to a Thing is to use the Thing.Lock class to acquire a read or a write lock. Of course, all of those Things need to be stored somewhere. Thus, the Thing class has another inner class, which is the Thing.Catalog and which holds all of the Things. This class is protected so that you can't access it from outside the Thing class.

The Thing.Catalog class is immutable, but -- like the Thing class! -- it contains an inner Thing.Catalog.Mutable class and a Thing.Catalog.Lock class. In this particular implementation, the Thing.Catalog is a singleton, so there's only one instance in the application that holds all of the Things.

So let's add a new Thing to the Thing.Catalog. All we do is create a new Thing and call its catalog() method. Since the catalog() method is internal to Thing, it can access the protected Thing.Catalog and obtain a Thing.Catalog.Lock for writing, giving access to the Thing.Catalog.Mutable. This allows us to add the new entity to the Thing.Catalog without ever exposing the Thing.Catalog to an external user -- because if we did expose the Thing.Catalog, then an external user could look up a Thing without getting a lock on the Thing simultaneously. And that would be bad, even if they did have to use the Thing.Catalog.Lock to do it. :)

The happy news is that these objects can inherit most of the locking code from an abstract base class, so you don't have to write a lot of new code in any given Thing to support this. My Thing class is in a file that's only about 275 lines long (with lots of blank lines for readability, but not yet any Javadocs), despite having five different inner (or inner inner) classes.

And it does what I want it to do, which is also happy news.
billroper: (Default)
So I've got the clock opened up and spread across the floor on my work computer as I try to rearrange some of the very early utility code that I wrote in Java to be a good bit cleaner than my original implementation. This means that pretty much nothing was compiling.

But one of my co-workers is working on some code using my new request factory on his machine, so I've been updating the various classes that it needs and checking them in so that he can get what he needs. Since this is the first field test of the request factory, it's not surprising that I needed to update it.

And then I discovered that some of the XML that we're being sent is in nothing like the format that I'd expected. I figured out how to work around that, but in order to do it, I need to change the two functions that read the XML for an object (one for attributes; the other for embedded elements) so that they return a boolean value to indicate whether or not they've processed a particular attribute or element. (Before this latest development, a void return had been just fine.)

Almost every object implements the XMLSerialize interface that I wrote, which means they define the XML reading functions, which mean that they all need to return a value that they didn't return before, so they all have to be modified.

Each compilation in JDeveloper will find exactly one file that lacks the return values.

It strikes me that this is a sub-optimal approach to compilation...
billroper: (Default)
I was making good progress at porting my grid code to Java, but then I hit the point where I needed the incomplete access control package.

So now I'm porting more of the access control package.

I could make some ham and beans soup.

If I had some ham.

And some beans.

And maybe a pot to cook it in.

Water would be good too...
billroper: (Default)
I'm hoping to avoid two steps back. :)

I've checked in a framework for a Java API where you would create a Request object on a Java client, populate it, and then pass it an OutputStream so it can write its XML description onto the stream that is connected to the Java server on the other end. The Java server passes it to an object factory that will read the XML and create an extended version of the Request object that includes a Run() method. The Run method executes on the Java server and writes data back into the object. When you're done, you pass it the OutputStream that connects back to the Java client and it writes the XML for the response. Then the Java client passes the stream to an object factory that pulls up a new copy of the original object, but with the response information in it.

We'll see what everyone thinks of it...

I've also written the basic code to handle object locking on the Java server. It will (in an act of heresy) use the try-with-resources feature in Java 7 and create a lock object to wrapper each of the underlying locks so that we can make sure that they get closed.

Because, you know, the penalty for creating an object to wrapper the lock is a lot less painful than the penalty you pay when someone forgot to release a lock on some obscure pathway through the code...

But it was a productive day of work as I wrapped up a couple of things that I'd been working on. :)
billroper: (Default)
Back to the Loop again today for another round of meetings.

I did manage to spend a few more minutes on the locking scheme for the server-side of my Java code. At this point, I'm looking at having all of the lockable objects on the server define three inner classes: the first being an immutable class that holds all of the data for the mutable outer class, the second being a private class that provides a locator / index for the objects so that you can find them with a key, the third being a public class that allows you to obtain either a read lock or a write lock and that will give you access to either the immutable inner class or the mutable outer class, depending on the type of lock that you've obtained.

So in skeleton form, it would look like this:
public class MyClass implements LockableObject {
  public class Const {
    boolean    member;

    Const( boolean member ) {
      this.member = member;
    }

    boolean getMember() {
      return this.member;
    }
  }

  private class MyIndex implements Index< Key, MyClass > {
    MyClass find( Key key ) {
      ... implementation details and other useful operations elided
      return object;
    }
  }

  public class Lock {
    Key       key;            // key to use with the index to locate the class instance
    LockType  readOrWrite;    // enum defined elsewhere (READ/WRITE)
    MyClass   object;         // the object, once we've located and locked it, else null

    public Lock( Key key, LockType readOrWrite ) {
      this.key = key;
      this.readOrWrite = readOrWrite;
    }

    public boolean lock() {
      ... probably uses tryLock() etc on ReentrantReadWriteLock
      return success;
    }

    public MyClass get() {
      if ( isLockedForWrite()) { 
        return object;
      }

      return null;
    }

    public MyClass.Const getConst() {
      if ( isLockedForWrite() || isLockedForRead()) {
        return object.Const;   // is this vaguely the right syntax?
      }

      return null;
    }
  }
}


Ok, that's an awful mess of assumptions left out and I may have blown some of the syntax, as I haven't actually tried to compile this yet, but it looks like the right idea.

I think.

It Lives!

Mar. 21st, 2014 10:24 pm
billroper: (Default)
Well, the simple calculation test is now running. It's running about a third slower than the C++ code, which is not what I had in mind, but we'll see if I can find a few more points to optimize at. :)
billroper: (Default)
I managed to successfully read the user-defined property set out of our file with the POI library. The serialization still doesn't match up between the Java and the C++ code, but we can straighten that out tomorrow.
billroper: (Default)
For the test project that I'm working on, I needed to take our binary data and present it in XML in exactly the format that we currently use, except that I had to do it in Java.

Ok, I can make that happen:

  • Open the document file with Apache POI.
  • Write the header for the XML document with the StAX XMLStreamWriter.
  • Write the header for a stream to the XML document with the XMLStreamWriter.
  • Open a stream from the document and read it into a byte array.
  • Compress it with the Deflater class.
  • Write the compressed and uncompressed length of the byte array to the XML document with the XMLStreamWriter.
  • Wrap the resulting compressed byte array in a ByteArrayInputStream.
  • Wrap that in a Base64InputStream to encode it.
  • Wrap that in a InputStreamReader to convert it to characters.
  • Now read characters from the InputStreamReader and write them out to the XMLStreamWriter, wrapped in an opening and closing tag.
  • Repeat until all streams are in the XML stream.

    I had to play a few games with the property sets, because I had used a different method to put those into the original XML response, but I eventually sorted that out.

    This is obviously non-optimum, because I really don't want to have to have both the compressed and uncompressed versions of the stream in memory at the same time, but since the current XML response is formatted that way, we'll live with it for the time being.

    Whee!
  • billroper: (Default)
    The substantially rewritten parser is now running.

    It is not yet running properly, but that's what debugging is for. :)

    (I've already fixed about half-a-dozen minor bugs, mostly introduced by having to use new String handling functions that are different from the ones I used in C++. More to fix on Monday, to be sure...)
    billroper: (Default)
    I added another new helper class to the parser -- actually to the Parseable helper class. This will fetch a function call and any / all of its arguments and store them in the class, which allows the code to be much simpler and more consistent. So you call the getFunction() method on a Parseable object and, if the Parseable object is a function call, it passes back a FunctionInfo object with the correct Function enum member and an array of arguments to the function as Argument objects (which extend Parseable, so any of them can be parsed themselves).

    Then I just pick off the Function enum and route the FunctionInfo object to the specific parser method that generates the correct byte codes for the function and its arguments.

    Patching all of this in is a bit tedious, but I suspect it will greatly improve my debugging and testing later. :)
    billroper: (Default)
    I had just about finished rearranging the parser logic in Java, when I realized that I could substantially improve my life by adding a helper class that keeps track of the current bit of the string that's being parsed, the position of that string relative to the original string (for error messaging), and the operator to apply to the bit of string once the parsing is complete.

    So I'm refactoring. The resulting code will be much easier to live with and quite likely much easier to convert to some "standard" parsing system in the future, if that proves to be helpful.
    billroper: (Default)
    Last week, I started browsing through the source code for the Apache POI library, because the examples and documentation that I'd been finding were woefully inadequate for the task I was working on. Today, everything finally clicked when I came to realize that there just doesn't seem to be a way to use POI to write a compound document back out into the original file. (Maybe there's something that will do it there, but I haven't found it yet.)

    So I've now managed to recode everything to write the changed streams out to a new file, along with all of the unchanged streams from the old file. And that seems to be working fine now.

    On to the next little bit... :)

    51,201

    Feb. 11th, 2014 06:17 pm
    billroper: (Default)
    Not counting the smaller (but, in some cases, still significant) side packages that amount to another 9000 lines of code, I have now ported 51,201 lines of C++ code to Java.

    Using this code base, I am able to open up two entities, add them up into a third entity, and write the results back to disk in a way that our current product can read.

    And there was much rejoicing. :)

    Profile

    billroper: (Default)
    billroper

    October 2025

    S M T W T F S
        1234
    567891011
    12131415161718
    19202122232425
    262728293031 

    Syndicate

    RSS Atom

    Most Popular Tags

    Style Credit

    Expand Cut Tags

    No cut tags
    Page generated Oct. 2nd, 2025 12:15 pm
    Powered by Dreamwidth Studios