Migrating from C# to Java

For some time now, I’ve been working to turn some C# code into a Minecraft mod. This is a short post about some hurdles I encountered having only using C# minimally. Unintentionally, I have also become quite jealous of some of the additional features C# offers that Java does not have, or does not do very well.

Generics

First and foremost: C# does Generics right – or at least better than Java. While Java simply utilizes Generics as type erasure, C# allows greater flexibility and introduces additional capabilities like instantiation of the generic parameters.

For example, this is not legal in Java, but the similar C# code would be:

public List<T> makeNewListWithOneItem( ) {
  List<T> myList = new ArrayList<T>();
  myList.add( new T() );
}

So much of what you encounter when trying to migrate code may be a tad more difficult to compensate for, should that code utilize these features. The way I personally worked around it was to include the actual class as the first argument.

public List<T> makeNewListWithOneItem (Class clazz) {
  List<T> myList = new ArrayList<T>();
  try {
    myList.add( clazz.newInstance() );
  } catch ( InstantiationException | IllegalAccessException e ) {
    // blah blah blah
  }
}

It’s not quite as nice, but it should work for those cases where ‘generic parameter instantiation’ is required.

Refs

C# has the concepts of ref, in and out. A nice summary of the differences is:

  • ref is used to state that the parameter passed may be modified by the method.
  • in is used to state that the parameter passed cannot be modified by the method.
  • out is used to state that the parameter passed must be modified by the method.

As Java is pass-by-value, this introduces a problem in how to get it to pass by reference when the code calls for it. While any called function that modifies the internals of the object will work as expected, wholesale reassignment will not be reflected outside of the method call.

abstract class Animal {
    public String name;

    Animal(String name) {
        this.name = name;
    }
}

class Dog extends Animal {
    public Dog() {
        super("Dog");
    }
}

class Cat extends Animal {
    public Cat() {
        super("Cat");
    }
}

public class RefTest {
    public static void main(String[] args) {
        Cat cat = new Cat();
        reassign(cat, "NotACat");
        System.out.println("Reassigning cat name = " + cat.name);

        cat = new Cat();
        reassign(cat, new Dog());
        System.out.println("Reassigning cat to dog = " + cat.name);
    }

    public static void reassign(Animal animal, String toName) {
        animal.name = toName;
    }

    public static void reassign(Animal animal, Animal otherAnimal) {
        animal = otherAnimal;
    }
}

Outputs:

Reassigning cat name = NotACat
Reassigning cat to dog = Cat

A good IDE will even warn about this in the secondary reassign by graying out the assignment, since it will have no effect.

There are several ways to work around this, but the one I’ve chosen would be the use of a encapsulation

class Ref<T> {
    private T innerObj;
    
    public Ref(T obj) {
        this.innerObj = obj;
    }
    
    public T get() {
        return innerObj;
    }
    
    public void set( T obj ) {
        this.innerObj = obj;
    }
}

In this way, any place a ref is needed, the object can be passed as the encapsulated Ref object

public class RefTest {
    public static void main(String[] args) {
        Ref<Animal> cat = new Ref<>(new Cat());
        reassign(cat, "NotACat");
        System.out.println("Reassigning cat name = " + cat.get().name);

        cat = new Ref<>(new Cat());
        reassign(cat, new Dog());
        System.out.println("Reassigning cat to dog = " + cat.get().name);
    }

    public static void reassign(Ref<Animal> animal, String toName) {
        animal.get().name = toName;
    }

    public static void reassign(Ref<Animal> animal, Animal otherAnimal) {
        animal.set(otherAnimal);
    }
}

Note that we’ve change the type to Animal to allow the reassignment.

Now this outputs:

Reassigning cat name = NotACat
Reassigning cat to dog = Dog

By doing this, we are able to effectively pass by reference by taking advantage of the ability to modify the internals of the object, though not the object itself. We’ve simply changed the value we are passing from Cat to Ref<>

Slow performance with CXF and Jetty

I am, quite admittedly, far from an expert with CXF. When I was tasked with upgrading an old CXF 2.x / Jetty 8.x service to CXF 3/Jetty 9, I hoped it would be a fairly simply task of modifying a pom and perhaps a few configuration points and being done. Unfortunately, I found myself needing to upgrade quite a few pieces, dependencies and customized connectors. But even that wasn’t the biggest problem.

Once all the dependencies, security and customized pieces were completed and all the tests were passed, we were ready to place the service into a non-production environment. This environment is far from isolated, as it receives on average 150+ TPS for a single instance. But, all the tests were completed so no problem, right? Unfortunately, from the moment it was started, there were issues.

CPU usage skyrocketed, calls that took milliseconds now took (literally) minutes and the log was filled with Broken Pipes. Thread dumps showed a plethora of stacktraces leading back to XMLStreamWriterImpl and java.lang.String.toCharArray. It seems something was getting stuck outputting the XML responses, but all of the elements in the stack trace were third party – none of it really had anything to do with our application code.

Searches on StackOverflow and other places turned up nothing. At first, we couldn’t replicate in a standalone environment until finally – we could. Turns out that after checking nearly everything, the classpath was the issue. After more searching, we had transitive dependencies pulling in the jaxp-ri library, which appears to have been taking precedence over what did actually work properly, which was StAX. So if you happen to ever find yourself in a similar situation, make sure to check those transitive dependencies for rogue elements!

As a side note, I’m still not 100% clear on exactly why this performed so abysmally with the jaxp-ri library. If anyone happens to have any insight into that, as my time for such endeavors is often lacking, feel free to drop in a comment or two.

DME

DME – What is it?

AT&T’s DME (which stands for Direct Messaging Engine) is a Java-based open source library for performing service lookups with built-in support for a file-based service directory, AT&T’s GRM (open source version GRM-Edge which is slightly different and will be explained in another post), or hooks for custom service directories.

Ok… so?

DME provides client or server location-based (or custom) endpoint ordering with customizable failover support that provides minimal overhead for HTTP, JMS (over HTTP) or JDBC communications. Basically, this allows for accessing redundant systems in a fault-tolerant capacity whether the system is focused on transactions, data retrieval or fire-and-forget data insertion.

Aren’t there already tools that do this?

Probably! I’m not aware of them (and quite honestly I haven’t searched very hard for them), but please leave some info in the comments if you’re aware of similar tools and I can get some comparisons/contrast. I’m only providing this information because DME is something I’m quite familiar with, having worked on it directly.

 

This is a basic overview of the flow of how DME works:

1) Client requests communication via DME, which talks to a service registry

2) Service Registry returns relevant information about the services (host, port, path, etc.)

3) DME selects the closest endpoint(s) and attempts to contact them

4) If failure occurs talking to the closest set, DME can talk to those farther away as a back up. For instance, in the image, if DC A goes down, it will failover to DC B.

 

Simple SSL for Developers

Overview

There are many (good) resources out there for SSL and its underpinnings. There are detailed forays into the dark underbelly of handshake, encryption, certificates, keystores and the like. But how much do you really need to know? Surely, pursuit of absolute knowledge is a noble task, but when you’re on the company dime, just short on time, or … something else that ends in -ime, maybe you just need to know enough to get past your problem and move on to other things.

First thing to know is that SSL (as a protocol) is essentially dead, although perhaps obsolete is the better term here. The latest craze is TLS 1.2 with 1.3 on its way as of this writing. Why TLS? Because it’s more secure, of course! People still generally refer to secure communications over http as SSL, but the protocol of choice is TLS due to vulnerabilities in the original SSL, SSLv2 and SSLv3 protocols. We’ll continue to refer to the process of securing communication as “SSL” throughout this page, but bear in mind that we’re talking about the process, not the protocol.

Second, we need to differentiate between One-way SSL and Two-way SSL. The difference between them is really as plain as it seems. One-way SSL is when the client needs to validate the server, but not vice versa. Two-way SSL is, as you might expect, when both the client and server need to validate each other. We’ll get into how that happens later, but for now just know that those are two are the basic varieties of “who needs to trust who”. One-way SSL is by far the most common, and is what you most often encounter when banking or using any secure website.

Third, we need to understand the parts of how SSL works. I’ll try not to get into too much detail here (as I mentioned, there are plenty of good sites for that), but as a broad overview the important pieces (from a developer standpoint) are the handshake and the certificate exchanges.

The handshake consists of agreeing on a protocol (e.g. SSLv2, SSLv3, TLSv1.1, TLSv1.2), agreeing on a cipher (the mechanism for encryption) and performing the actual certificate exchange and verification. When you encounter an issue, this is one big place where things can go wrong.

The certificate exchange itself involves the server providing its certificate to the client, which the client verifies. In Two-way SSL, the client will also send its own certificate to the server to be verified. The respective certificates are stored in a key store (one on the client, one on the server) and are verified by using a trust store (again, one on the client, one on the server).

Where can things go wrong?

Lots of things can interfere with valid communication between two services via SSL. We’ll work our way through the handshake to highlight some examples. Note that these examples all will reference the use of Java, but these issues themselves are not necessarily language related.

Handshake Protocol Selection

In order to be able to handshake, the client and server must be able to agree on how to talk. Beyond that, they must also agree on how to handshake. There is a somewhat problematic protocol called SSLv2Hello that can cause issues when the server is more restrictive on which protocols it accepts. SSLv2Hello (like all the SSL protocols) is considered vulnerable to attack and so, rightly, it should not be used. But upgrades take time and can be forgotten and adoption by end users can be slow. So sometimes these protocols hang around longer than they really should.

SSLv2Hello is not a normal SSL protocol in that it’s not used for sending any actual messages. It’s a ‘pseudo-protocol’ that’s used to perform the handshake. So how can you perform a handshake with a protocol that is known to have vulnerabilities when connecting to a server that is restricted to TLS? Easy – you can’t.

Sometimes this manifests itself plainly by stating that SSLv2Hello failed. Other times it’s more cryptic, like “Early EOF Exception”. Debugging these can be a bit trickier – you’ll often need to know the protocols the server supports beforehand or be able to debug the SSL connection. In Java, adding -Djava.net.debug=ssl should help.

So how do we disable SSLv2Hello from ever being used in the first place? In Java we can utilize the -https.protocols and jdk.tls.client.protocols flags to “TLSv1.1,TLSv1.2” (for example) to include only TLS protocols v1.1 and 1.2.

Invalid Cipher Selection

Just like protocols, ciphers can be compromised as well. It can be more difficult to diagnose these situations when dealing with a simple generic Java exception. Again, adding -Djavax.net.debug=ssl can help pinpoint the issue.

Additionally, there are legal restrictions on the strength of ciphers that can be exported from the United States (outside of the United States, you’ll have to consult the applicable laws). In the event that you are inside the United States, you may simply need to allow other ciphers to be used. For Java, those are found here.

Certificates

Certificates can be thought of as ID cards that two entities might show to each other to prove they are who they say they are. When you contact your bank and enter your password, you want to make sure that they are who they say they are! So imagine when you go to the bank, the teller shows you identification that verifies the teller’s identity. But we can’t just trust the teller, or even the ID. We also must trust whoever issued that ID. In this case, the ID itself is analogous to the certificate, while the issuer is analogous to the Root Certificate Authority (Root CA’s).

Windows and Java come pre-installed with a list of Trusted Root CA’s that are generally recognized as, well, trustworthy. If they issue a certificate to a server, then that server (according to the powers that be) can be trusted as well. This is all well and good, but ID’s (and certificates) don’t get issued for free! (Well, sometimes they do)

Often times during development, it’s too costly or time-consuming to procure valid certificates signed by recognized Root CA’s, so a self-signed certificate is used. Since it’s development, this in and of itself usually isn’t a problem, but it can be if your client isn’t set up to trust that certificate. (In Java, this usually manifests itself with a “PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target” or similar message) Many people recommend what amounts to turning your SSL Certificate Validation off (AKA trusting all certificates). This gets you past the issue and lets you proceed but is not recommended because often times this slips past into production and then things can really get compromised!

So another possibility is to simply add the server’s certificate to the client’s trust store. This takes a few more steps, but it is easier once you’ve done it a few times. A walk-through for that is coming but the steps involve using the browser to download the certificate. Once that is done, I’d recommend copying over the default java cacerts and adding the certificate to the new truststore using Java’s keytool command. Then you’ll have to tell your client to use the new truststore instead of Java’s default by using -Djavax.net.ssl.trustStore and -Djavax.net.ssl.trustStorePassword.

For Two-way SSL, the reverse has to take place as well. While you may have to type in your banking password to get into your account, another option would be to prove to the bank that you are who you say you are via certificate as well. This generally isn’t the case for current websites, as it would be too cumbersome for each and every customer to go and procure valid certificates that the bank trusts, but it is an option in environments where a smaller number of unique hosts communicate.

And those are the major points of general issues faced by developers when using SSL. Certainly there is more (much more!) to cover, but most of the time the issue falls into one of those categories. As time permits I’ll add diagrams and walk-throughs, but if you’d like to see additional details or examples, feel free to leave some comments and I’ll try to prioritize those. Thanks for reading!

Greetings and Salutations

This is just an opening post to place some semblance of an introduction to what will undoubtedly be a forgotten collection of ne’er before (or after) seen posts. Supposedly, at some point, I’ll add some random words and sentence fragments regarding my coding experience and perhaps logical musings in general. In the event that someone actually discovers this by an unfortunate turn of events, let it be known that all risks associated with the use of this site are borne by the user. Thanks, and enjoy the show.