Wave Motion Technology

"Improving the quality of the applications and services provided by America's public sector."

Reclaim 1.1GB of "swap" space on Mac OS X High Sierra

This post is not about APIs, but about how to solve one of the strangest issues I've run into on Mac OS X…

Some background: one of the best purchases I made before I started Wave Motion Technology was a
refurbished iMac Pro 18-core desktop with a 2TB SSD. I bought it because I knew I would be doing lots of work with virtual machines and containers, and I wanted to have as much horsepower locally so that I could create mock environments where I control every aspect of my environment.

While I'm not certain of the root cause of the issue (but I do wonder if my heavy use of VMware Fusion for Mac is a potential culprit!), I noticed that my SSD was rapidly filling up, to the point where at one point it claimed I was using 1.97TB of storage and was unable to download the latest Xcode update from Apple.

I moved my massive (600GB) Photos library to an external drive. I deleted a few of the larger files hidden away in the ~/Library/Caches directory.

No improvement.

In fact, even after deleting files and directories like a madman, the drive still showed 1.97TB used.

My mood during this bug hunt was in sync with Ferrari Formula 1 drivers this season who are having a horrible time of it…

6E1E6D97-4050-45D6-99E1-A67F305973C5


After some digging around (Okay, I googled it!), I found
this handy post about how one person solved the issue of missing disk space on an older version of Mac OS X, and after carefully following his instructions, I freed up 1.1TB of storage ultimately reclaiming the space that should have been reallocated much earlier.

The Mysterious Case of Catalina and the Missing Disk Space

How to enforce CRLs with the Layer 7 API Gateway

Curious about how to use Certificate Revocation Lists (CRLs) with the Layer 7 API Gateway? Here's a video that explains how it works... be sure to watch it in full HD to see the gory details!

Link to video:
https://youtu.be/RUA4svpw9qc

API Gateway 10 and ActiveMQ 5

Good News, Everyone!


After doing some preliminary testing, I can confirm that the Layer 7 API Gateway version 10.0 works with the ActiveMQ 5.15.11 using the same steps outlined in my earlier post

Configure Layer 7 API Gateway and ActiveMQ 5 to use Openwire instead of AMQP



While evaluating various messaging products, I've come across
ActiveMQ quite a bit, and I've found it to be more than adequate for application and enterprise messaging. In the course of my work, I have also had to integrate the Layer 7 API Gateway with ActiveMQ, and found an interesting quirk…

The
documentation does explain how to configure the API Gateway to reference JMS destinations in ActiveMQ, but only using the AMQP protocol. While doing some performance testing, I decided to investigate what would be involved in configuring the API Gateway to use ActiveMQ using the Openwire protocol and to compare that with the AMQP protocol.


Caveat: These instructions are specific to the Layer 7 API Gateway 9.4 and ActiveMQ 5.15.11. Your mileage may vary!


Step 1: Stop the API Gateway



First, shut down the API Gateway services. On the appliance version, you can do this by running:

service ssg stop


Step 2: Copy the client JAR files from ActiveMQ to the API Gateway

You'll need the following files from the
lib directory in your Apache ActiveMQ installation.

  • activemq-client-5.15.11.jar
  • geronimo-j2ee-management_1.1_spec-1.0.1.jar
  • geronimo-jms_1.1_spec-1.1.1.jar
  • hawtbuf-1.11.jar
  • jcl-over-sl4j-1.7.25.jar
  • slf4j-api-1.7.25.jar

ActiveMQ Client JARS

The API Gateway can load user-defined JAR files from the /opt/SecureSpan/Gateway/runtime/lib/ext directory.

This location is where you may place the JARs for custom assertions that extend the API Gateway's functionality, and files in this directory should be owned by the layer7 user and set to read-only. You'll notice that are some extraneous files in this listing because I have already copies the files over for using the AMQP protoocol with ActiveMQ.

ActiveMQ Client JARS - Permissions on API Gateway




Step 3: Start the API Gateway


You can now start the API Gateway. Again, on the appliance you can run the command:

service ssg stop

Step 4: Create a Web API policy


Start the API Gateway Policy Manager and use the
Publish Web API wizard to create an API with the following settings:

Service Name:
JMS Receive Message
Target URL:
Gateway URL:
/jms/receive (this is irrelevant for this example)

And click
Finish.

In the editor window, add an
Add Audit Details assertion to the policy with the following settings:

JMS Receive Policy



Step 5: Configure the JMS Destination(s) in Policy Manager


Using the API Gateway Policy Manager and from the menubar, select Tasks —> Transports —> Manage JMS Destinations to open the Manage JMS Destinations dialog.




Manage JMS Destinations Dialog


Click Add, and now you can create an Inbound JMS Destination for subscribing to messages from ActiveMQ. Enter a Name (I called this one ActiveMQ Inbound), and select Inbound for the Direction.

ActiveMQ Inbound - Basics


Under the JNDI tab, you will need to set the following values:

Initial Context Factory class name:
org.apache.activemq.jndi.ActiveMQInitialContextFactory
JNDI URL:
tcp://your-activemq-hostname:61616
Credentials are required to connect to JNDI:
Checked
User Name:
admin (default credentials with ActiveMQ)
Password:
admin (default credentials with ActiveMQ)


Now
Add Additional Properties:

Name:
topic.MyCategory.>.
Value: MyCategory.>

The Additional Properties configuration is critical because the API Gateway is creating the
JNDI properties "object" for the ActiveMQ client that will contains all of the settings for the ActiveMQ queues, topics, and even connection factory names you may reference. For an Inbound JMS Destination, you will typically only need to specify a destination following the conventions in the ActiveMQ 5 JNDI documentation for naming your queues, topics, and connection factory names.

One nice feature is that the API Gateway does respect the use of
JMS wildcards for the destination name, allowing you to subscribe to multiple destinations seamlessly. In this example, my gateway will be receiving messages to any ActiveMQ topic whose JNDI name has the string "MyCategory" as its first component . This means it would receive messages to topics named MyCategory.events.birthdays or MyCategory.ABC.DEF.GHI.JK or just MyCategory.



ActiveMQ Inbound - JNDI

On the Destination tab enter the following settings:

Destination Type:
Topic
Connection Factory Name:
ConnectionFactory (you can specify a different value if you set the connectionFactoryNames property on the JNDI tab so that it includes the name of your connection factory)
Destination Name:
MyCategory.>
Credentials are required to connect to JNDI: Checked
User Name:
admin (default credentials with ActiveMQ)
Password:
admin (default credentials with ActiveMQ)


ActiveMQ Inbound - Destination

You can now click on the
Test Settings button and you should see…

JMS Connection Successful

Finally, we set the
Inbound Options. I recommend looking at the API Gateway documentation for more details, but the only setting relevant to this example is to change the Service Resolution settings to:

Associate destination with published service:
Checked
Service Name:
Receive JMS [/jms/receive]

This causes any message that is posted to the registered destination to be funneled to the Receive JMS Web API we created in Step 4.



ActiveMQ Inbound - Options


Step 6: Create an Outbound JMS Destination


Re-open the
Manage JMS Destinations dialog by selecting Tasks —> Transports —> Manage JMS Destinations. Select the JMS Destination created in Step 5 and click Clone.

In the Basics tab, change the settings to:

Direction:
Outbound
This destination is a template:
Selected

Since this is a template, we will be able to dynamically specify the destination in a gateway policy.

ActiveMQ Outbound - Basics


The Additional Properties settings on the JNDI tab need to be modified to list all possible destinations the API Gateway may want to use in policy. This is because the actual JNDI "search" for a destination requires an exact match for the name, with no wildcards allowed. For this example, we will set the additional properties to configure three possible JMS topics we can publish to:


Name:
topic.MyCategory.MySubcategory.MyName
Value: MyCategory.MySubcategory.MyName

Name: topic.MyTopic
Value: MyTopic

Name: topic.SomeOtherCategory
Value: SomeOtherCategory


ActiveMQ Outbound - JNDI



In the Destination tab, use the existing settings but clear the Destination Name field so that clients can specify the name in policy.ActiveMQ Outbound - Destination



Finally, for the Outbound Options, you can use the default settings. For performance testing, I turned the Outbound Reply Behavior to No replies (one-way).
ActiveMQ Outbound - Outbound Options

Step 7: Create a Web API Policy to Publish Messages



In Policy Manager, create another Web API with the following settings:

Service Name: JMS Publish Message
Target URL:
Gateway URL:
/jms/publish

In the policy editor, we will create a policy that allows us to post a simple XML message to a JMS destination whose name is provided as the HTTP parameter
destination.

JMS Publish Policy


The Route via JMS Assertion should be configured so that the
Destination Name is set to the variable ${destination}

JMS Publish Policy - Route via JMS Properties - Target

We will also need to set the Request settings so that the published message will be populated by the ${requestMessage} variable.
JMS Publish Policy - Route via JMS Properties - Request

Finally, since the browser will be used to kick off the JMS Publish Message policy, we should send back a reasonable response. Since this is a simple test, we'll respond with an HTTP 200 and a plain text message that says "OK"

JMS Publish Policy - Template Response Properties



Step 8: Test



You can use the browser to issue requests and test the JMS Publish Message policy at the URL
http://your-gateway-hostname:8080/jms/publish

By default, it will publish to the JMS Destination named MyTopic. To override this behavior, add a destination parameter to the URL
. Here are some valid examples based on the JNDI names specified back in Step 4:

http://your-gateway-hostname:8080/jms/publish?destination=MyCategory.MySubcategory.MyName


Test Output
http://your-gateway-hostname:8080/jms/publish?destination=MyTopic
http://your-gateway-hostname:8080/jms/publish?destination=SomeOtherCategory

Only messages sent using the first example (to the destination
MyCategory.MySubcategory.MyName) will cause the JMS Receive Message policy to be invoked, as it is subscribed to any message published to a topic whose name starts with MyCategory since it is subscribing to all destinations that meet the JMS wildcard pattern MyCategory.>

At this point you have now successfully configured the Broadcom Layer 7 API Gateway to use ActiveMQ 5 via the Openwire protocol. Congratulations!