Search

April 13, 2017

Publishing to the Maven Central Repository

As an exercise in creating a Java library and submitting it to the Central Repository, I created an implementation of the xirr (irregular internal rate of return) function in Java.

If you are interested in what needs to be done to publish to the Maven Central Repository, check out the pom.xml for starters. The distributionManagement section contains configuration for pointing to the Nexus Repository Manager at oss.sonatype.org. This Nexus installation is used as a staging platform for the Central Repository.

Next in the plugins section we include the maven-source-plugin and maven-javadoc-plugin in order to generate the source and javadoc jars for the repository. Your library will not be accepted without these.

Next there is the maven-gpg-plugin for generating signature files for the artifacts. In order to generate the signature files, you will need to have a GPG key and placed the public key on a keyserver. If you don't have this already, google for some GPG tutorials. More about this in a moment.

Finally in the pom.xml we have the nexus-staging-maven-plugin plugin configuration. This plugin overrides the standard deploy plugin to interact with the Nexus Repository Manager.

Both the oss.sonatype.org and the GPG key have authentication credentials which need to be managed as part of the build process. To begin, you need to create a maven master password if you have not already done so. If you are not sure, look for the ~/.m2/settings-security.xml file to see if it has a master element. All the passwords for maven configuration can be encrypted. To generate an encrypted master password, issue the command mvn --encrypt-master-password and then place the result in your ~/.m2/settings-security.xml:

Then you need to encrypt your passwords using mvn --encrypt-password and put them in your ~/.m2/settings.xml:

Note that the first server id corresponds with the id in the distributionManagement section of the pom.xml. The second server id is used by the maven-gpg-plugin by default. Of course that can be changed by configuration, see the documentation of that plugin for details.

Finally, there is a pretty cool implementation of the xirr function in there as well. Not to mention a concise implementation of Newton-Raphson using Java 8 features.

Additional Resources:

March 30, 2017

November 15, 2016

Connect to Microsoft VPN from Fedora 24

New box, new OS, time for another edition of trying to connect to Microsoft's VPN software. This time it is Fedora's turn.

This first part is adapted from my previous editions for Ubuntu and ultimately are sourced from an Ubuntu forums post by user sweisler at http://ubuntuforums.org/showpost.php?p=8261958&postcount=6. Thanks sweisler, wherever you are.

First, there was no need to install any additional packages, apparently everything needed is included by default.

  • Open VPN configuration screen:
    • Click on the network icon in the upper right of the desktop
    • Expand the VPN menu
    • Select VPN Settings
    • Select Configure VPN…
  • Add a new PPTP connection
  • In the Identity section, set the following:
    • Connection name (whatever you want)
    • Gateway (this is the VPN server)
    • User name (for domain-based user accounts, use domain\username or username)
    • Do not set Password; do change the pulldown (hidden in the help icon) to Always Ask
    • Set NT Domain if it is a domain-based account and you feel like it (I tried with User name as plain username and no NT Domain set, with User name as domain\username and no NT Domain and with User name as plain username and NT Domain set and everything worked - a far cry from when I was first trying to connect years ago).
  • PPTP Advanced Options (Advanced button from the Identity section)
    • Uncheck all authentication methods except MSCHAPv2
    • Check Use Point-to-Point encryption (MPPE)
    • Leave Security set at All Available (Default)
    • Check Allow stateful inspection
    • Uncheck Allow BSD data compression
    • Uncheck Allow Deflate data compression
    • Uncheck Use TCP header compression
    • Uncheck Send PPP echo packets (this setting works either way, check it for debugging purposes)
    • Leave Use custom unit number unchecked.

Normally at this point we would save and test the connection, but for Fedora there are additional steps. We need to configure the firewall to allow connections on the GRE protocol.

Note that GRE is a protocol like TCP or UDP, not a particular port.

The Fedora firewall demon allows you to make changes in two modes: permanent changes which affect the configuration but not the running instance and temporary changes which affect the running instance but not the configuration. To enable GRE traffic through your firewall, use the following command:

sudo firewall-cmd --add-protocol=gre sudo firewall-cmd --query-protocol=gre

Now test out your VPN connection. If it is working, save the changes to the configuration of the firewall:

sudo firewall-cmd --permanent --add-protocol=gre sudo firewall-cmd --permanent --query-protocol=gre

Note that if you have multiple network connections (e.g. wireless vs wired), it may be necessary to configure the firewall for each one.

Once the VPN connection is working you may want to try to tweak it further as described below.

One problem with the VPN I connect to is that all traffic ends up using the VPN when I am connected. This is less than ideal if you are connecting to servers on the internet while the VPN is connected since the traffic goes through the VPN server before coming to you. The following describes the settings for routing only the proper traffic to the VPN. (Read them all the way through first to make sure you have all the necessary information.)

Start by opening the IPv4 Settings section in the configuration of your VPN.

  • Set Additional DNS servers using the IP address of the DNS server for the VPN. (You may need to ask your IT guy for this; there should be a way to discover it when connecting as above but it escapes me.)
  • In the Routes section, add a new route:
    • For Address, use the internal IP address of the VPN server applied against the netmask below, e.g. if the VPN server is 10.23.34.89 and the netmask is 255.255.255.0, use 10.23.34.0. Again, this should be the internal IP address for getting to the machine in the intranet, not the external IP address for getting to the machine from the internet.
    • For Netmask, use the netmask of your intranet. (If you are confused, ask your IT guy what to use for both this and the Address.) For most networks this will be 255.255.255.0, but for many it will be different.
    • For Gateway, use 0.0.0.0.
    • Do not set the Metric unless you know what you are doing.
  • If necessary, add additional routes. E.g. you might have a DMZ in the 10.0.0.0/24 network in the VPN you are connecting to.
  • Check Use this connection only for resources on its network
  • In other versions of the NetworkManager configuration tool, there was a field for Additional search domains. This field is missing on Fedora 24 and some experimenting and testing seems to indicate we don't need it.

OK, so now when you connect you should see regular traffic going directly to the internet and intranet traffic directed to the VPN server. You can test this out with traceroute (which you may need to install).

Let me know how these instructions work for you and what type of systems you’ve been able to connect.

September 17, 2016

Dipping my toes into the Node.js ecosystem

Just to get my feet wet, I published a Node.js module called xirr.

When I was writing the unit tests for the module I had a particular case where the Newton's method implementation was not converging and the library I was using returned false. My son, who has done a bit of coding was shoulder surfing and was asking me what we needed to do to make the the value be true. When I explained that we actually wanted the library to return a number instead his head practically exploded. So I went into the difference between a statically typed and dynamically typed language and he asked "Why don't you just change it to statically typed?"

So, how about EmcsScript committee? Up for making ES7 a statically typed language?

August 21, 2016

Connect to Microsoft VPN from Ubuntu 16.04 Xenial Xerus

I recently upgraded from Ubuntu 14.04 on my main desktop machine and discovered that my VPN connection to Windows 2008 Server no longer worked. The bugaboo turned out to be the routing table which no longer requires a gateway entry. Here I have rewritten my post originally written for 12.10 to reflect the new configuration.

If you have ever tried to configure a linux machine to connect to a Microsoft-based VPN, you know that it is not as straightforward as it could be. It is more of a voodoo ritual than a science. I figured it would be a good idea to capture the steps for future reference.

This first part is adapted from the Ubuntu Wiki for posterity. You can check out the original at https://wiki.ubuntu.com/VPN under the heading VPN setup in Ubuntu 9.10. Apparently this originates from a Ubuntu forums post by user sweisler at http://ubuntuforums.org/showpost.php?p=8261958&postcount=6. Thanks sweisler, wherever you are.

First, there was no need to install any additional packages, apparently everything needed is included by default.

  • Open VPN configuration screen:
    • Click on the network icon in the upper right of the desktop
    • Go to the VPN Connections menu
    • Select Configure VPN…
  • Add a new PPTP connection
  • On the VPN tab, set the following:
    • Connection name (whatever you want)
    • Gateway (this is the VPN server)
    • User name (for domain-based user accounts, use domain\username)
    • Do not set Password; do change the pulldown to Always Ask
    • Do not set NT Domain
  • PPTP Advanced Options (Advanced button from the VPN tab)
    • Uncheck all authentication methods except MSCHAPv2
    • Check Use Point-to-Point encryption (MPPE)
    • Leave Security set at All Available (Default)
    • Check Allow stateful inspection
    • Uncheck Allow BSD data compression
    • Uncheck Allow Deflate data compression
    • Uncheck Use TCP header compression
    • Uncheck Send PPP echo packets (this setting works either way, check it for debugging purposes)

At this point save it and test it. Once the VPN connection is working you may want to try to tweak it further as described below.

One problem with the VPN I connect to is that all traffic ends up using the VPN when I am connected. This is less than ideal if you are connecting to servers on the internet while the VPN is connected since the traffic goes through the VPN server before coming to you. The following describes the settings for routing only the proper traffic to the VPN. (Read them all the way through first to make sure you have all the necessary information.)

  • On the IPv4 Settings tab
    • Set Additional DNS servers using the IP address of the DNS server for the VPN. (You may need to ask your IT guy for this; there should be a way to discover it when connecting as above but it escapes me.)
    • Set Additional search domains. Set this to the domain suffix of the machines on the VPN. For example, if the machines are named like dbserver.example.com then set it to example.com.
  • Click the Routes button.
    • Check Use this connection only for resources on its network
    • Add a route:
      • For Address, use the internal IP address of the VPN server applied against the netmask below, e.g. if the VPN server is 10.23.34.89 and the netmask is 255.255.255.0, use 10.23.34.0. Again, this should be the internal IP address for getting to the machine in the intranet, not the external IP address for getting to the machine from the internet.
      • For Netmask, use the netmask of your intranet. (If you are confused, ask your IT guy what to use for both this and the Address.) For most networks this will be 255.255.255.0, but for many it will be different.
      • For Gateway, use 0.0.0.0 or simply leave it blank.
      • Do not set the Metric unless you know what you are doing.

OK, so now when you connect you should see regular traffic going directly to the internet and intranet traffic directed to the VPN server. You can test this out with traceroute (which you may need to install). You should also be able to refer to machines on the intranet using their short names (e.g. dbserver instead of dbserver.example.com).

Let me know how these instructions work for you and what type of systems you’ve been able to connect.

April 4, 2016

Complicated String Joins

So if you have not been under a rock and have used Java 8, you are surely aware of the new String.join() method and the Collectors.joining() method to concatenate arrays or streams of Strings. Sometimes however, a simple concatenation with a delimiter is not quite up to the job.

Consider the following method for example:

Here our plans for a simple invocation of Collectors.joining() is complicated by the intermediate String literals and the particular format desired for the string representation of the entry.

At first blush you might attempt to change this to functional style using something like this:

If you are an old salt at Java however, I'm sure your hair is standing on end considering all those temporary String objects being created. Fortunately, using Stream.of() and Stream.flatMap() there is another way:

If you want to play around with this code, it is available on GitHub at StringJoin.java

March 28, 2016

Creating a custom Collector

Creating a custom implementation of java.stream.Collector seems daunting at first, but once you give it a try, you'll see that it can actually be pretty easy.

If you are not used to using lambdas and functional concepts, your first look at the Collector interface will be intimidating. From a pre-Java 8 perspective, there are four interfaces to implement to create a custom Collector implementation: java.util.function.BiConsumer, java.util.function.BinaryOperator, java.util.function.Function and java.util.function.Supplier. Fortunately they are all functional interfaces which will allow us to take some shortcuts with lambdas and functional expressions.

The example I chose to implement is a Collector for SetValuedMap from Apache's Common Collections project. We'd like a static method similar to the standard Collectors.toMap() method which will generate a Collector instance yielding a SetValuedMap implementation.

There are a lot of moving parts to the Collector in terms of generics. First, we will have generic parameters for the type in the existing stream <T>, the type of the key in the map <K> and the type of the values in the map <V>. Then we need to identify the three generic parameters to the Collector interface: <T> is the same as before, the type of objects in the stream; <A>, the accumulation type will be SetValuedMap<K,V>; and <R>, the result type, will also be SetValuedMap<K,V>. It is frequently the case with Collectors that <A> and <R> are the same.

Now that we have our generic ducks in a row, we can start figuring out our Collector implementation. For the supplier, we can use a constructor of a SetValuedMap implementation, e.g. HashSetValuedHashMap::new.

The accumulator will be a lambda function taking in a map and a stream object, it will need to put the stream object in the map. For that we will need to pass in functions converting the stream objects to keys and values respectively (just like in Collectors.toMap()).

The combiner will need to accept two maps and return a map containing entries from both. Again this can be specified with a lambda function.

We don't need anything beyond the identity function for the finisher, which means we ready to create our Collector implementation using the Collector.of() factory method:

This method can be used to create a version of Collectors.groupingBy() which eliminates duplicates simply by passing Function.identity for the valueMapper:

If we wanted to get really fancy we could also pass in a Comparator to use with our set, but I will leave that as an exercise for the reader.

See the file MoreCollectorsTest.java for some examples of these methods in action.