Skip to content

Name the properties wanted on the cloud Pipeline builders, and test a license key alone against the live service - #131

Merged
jwrosewell merged 5 commits into
rcfrom
feature/cloud-builders-requested-properties
Nov 14, 2026
Merged

jwrosewell merged 5 commits into
rcfrom
feature/cloud-builders-requested-properties

Conversation

@jwrosewell

@jwrosewell jwrosewell commented Nov 14, 2026 •

Copy link
Copy Markdown
Contributor

Closes #12.

Problem

#12 asks for a Cloud Request Engine that authenticates on a license key alone and names the properties it wants. #97 put that into CloudRequestEngineBuilder and CloudRequestEngineDefault, which are on rc. Two parts of #12 were still missing on rc at 30e4886.

  1. The cloud Pipeline builders could not pass the properties on. DeviceDetectionCloudPipelineBuilder (lines 90 to 95), IPIntelligenceCloudPipelineBuilder and GeoLocationCloudPipelineBuilder set only the two keys on the Cloud Request Engine builder, and CloudPipelineBuilderBase had no option for the properties. So an application that builds its Pipeline with one of these builders and a license key alone was always refused, because the engine builder was given no properties.
  2. No live test authenticated on a license key alone. The only live test, CloudRequestEngineLiveTests.build_Process_ReadsDeviceDataFromTheLiveService, always sets a resource key. Point 7 of Authenticate a Cloud Request Engine on a license key alone, and name the properties wanted #12 asks for "a live test against the service that authenticates on a license key alone and catches the silent drop, skipping cleanly when no license key is configured".

What the specification says

The Cloud Request Engine specification at 6570727d, "License Key", says:

A License Key is the credential held by the server and never published to the browser. Unlike a Resource Key it names no Properties of its own, so a caller that authenticates with a License Key alone MUST also supply the list of Properties it wants.

"Requested Properties" says:

Requested Properties is the list of Properties the caller wants in the response. It is sent to the remote server using the key values, as a comma separated list of fully qualified Property names, for example device.ismobile,device.iscrawler.

"Accepted combinations" gives seven rows, of which two are invalid, a License Key with no Requested Properties and no credential at all, and says "An Engine MUST refuse an invalid combination when it is built, in its builder or constructor, rather than when a request is made." #12's own table gives three invalid rows. The third, a Resource Key with Requested Properties, became valid in the specification after #12 was written ("Each requested Property is added, as null with a reason where no licence grants it."), and the engine builder on rc follows the specification (checkCredentials, lines 220 to 235). This draft changes none of those rules.

"Properties the remote server did not return" says an engine that sent Requested Properties "MUST therefore compare what it asked for against what came back, and report the difference", that "A Property that is present but null MUST count as answered rather than dropped", and that "The report MUST be made once rather than on every request". The new live test checks each of those against the service.

What changed

  1. CloudPipelineBuilderBase gains setRequestedProperties(List<String>) and setRequestedProperties(String), the second taking one comma separated string. They have the names and arguments of the two methods on CloudRequestEngineBuilder, and both refuse null with IllegalArgumentException, as those do.
  2. DeviceDetectionCloudPipelineBuilder, IPIntelligenceCloudPipelineBuilder and GeoLocationCloudPipelineBuilder pass the list to the Cloud Request Engine builder when it is not empty. The engine builder trims the names, drops empty ones and applies the specification's table, so the Pipeline builders hold no rule of their own. A license key alone with no properties is still refused by the engine builder, with its message that the service "answers 400" and that names setRequestedProperties.
  3. GeoLocationCloudEngine.loadAspectProperties read DelayExecution from the accessible properties answer as a Boolean and passed it where a boolean is needed, so a property whose answer has no DelayExecution field stopped the Pipeline build with NullPointerException. The new Location builder tests found it (commit 9810a61). A missing DelayExecution is now false and a missing list of evidence properties is an empty list, which are the values a property with neither has.
  4. CloudRequestEngineLiveTests.build_Process_LicenseKeyAlone_AnswersOnlyWhatWasAsked builds an engine on a license key alone and asks for three names, being a property the license grants, device.ismobile and a name that is not a property. It processes twice and checks that the answer has no errors, that device.ismobile is answered with a value or as null with its nullreason, that the answer holds nothing that was not asked for, and that the engine logged the left out name in one warning and not two. It skips when no license key is set, or when the one set grants no cloud product. None of its messages holds the service's answer, only the names of the answer's fields, so nothing the service says about a key reaches a build log.
  5. The Cloud 51Did Tests workflow also runs that one test, and starts on a change under pipeline/pipeline.cloudrequestengine. It is the only workflow given a license key for the cloud service, so in every other build the test skips.

Every name is new. No public name is removed or renamed, and an application that never calls setRequestedProperties sends what it sent before.

Tests

Written first (commit 6480cc1). DeviceDetectionCloudPipelineBuilderTests, IPIntelligenceCloudPipelineBuilderTests and GeoLocationCloudPipelineBuilderTests each build a Pipeline against an HTTP client that records the data request, and each has the same six tests.

  • LicenseKeyAlone_RequestedProperties_SentAsValues and LicenseKeyAlone_RequestedPropertiesAsText_SentAsValues. The request carries license and values, and no resource. The text form is given as device.ismobile, device.iscrawler and sent without the space.
  • BothKeys_RequestedProperties_SendsAllThree.
  • ResourceKey_NoRequestedProperties_SendsNoValues, so a caller that names nothing sends what it sent before.
  • LicenseKeyAlone_NoRequestedProperties_Refused. The build stops with PipelineConfigurationException, the message says why and does not hold the license key, and no request is made.
  • SetRequestedProperties_Null_Refused, for both methods.

The runs build the three modules with the modules they need and run the three test classes on the runner's Java, on Ubuntu.

  • Red, the tests on rc (commit 002805e on a temporary branch): run 43532206552. The test build fails with "cannot find symbol" for setRequestedProperties in all three modules, because the Pipeline builders on rc have no such method.
  • Green without the Location fix (commit 593f149): run 43532247241. Device Detection and IP Intelligence pass 6 of 6. Four of the six Location tests end in the NullPointerException of point 3 above.
  • Green, commit 33361f6, which is 9810a61 with the temporary workflow added: run 43533718269. 6 of 6 in each of the three classes.
  • Live, the Cloud 51Did Tests workflow started by hand on the earlier head 758e0f7, before rc 1c99b72 was merged in: run 43534359725. With the 51Did license key the license key test ran and passed, and with a key set that has no license key beside it the test skipped.

The live test has no red run, because the engine code it runs is already on rc through #97. It is a check of the service.

Measured while writing the live test

Measured against cloud.51degrees.com on 14 November 2026 with the 51Did license key alone, in run 43535823198, which prints only the status and the names of the fields in each answer.

values Answer
a property the license grants, and device.ismobile 200, ismobile and ismobilenullreason, no errors
the same two and device.notaproperty51d 200, the same fields, no errors, and nothing for the third name
device.ismobile alone 200, ismobile, ismobilenullreason and errors
device.notaproperty51d alone 200, errors only

So a property the license does not grant, asked for beside one it does, now comes back with a nullreason beside it, where the specification's measurement of 21 September 2026 found it "dropped from the response without being named". The engine on rc already treats both in the way the specification asks, counting the null as answered and reporting the name that is left out once, which is what the live test checks.

Build

The full build of the head ec978df is run 43594483320, and it is green. All nine Build and Test jobs passed (Ubuntu on Java 8, 11, 17 and 21, Ubuntu ARM on Java 17, and Windows on Java 8, 11, 17 and 21). In every job the three new builder test classes (DeviceDetectionCloudPipelineBuilderTests, IPIntelligenceCloudPipelineBuilderTests and GeoLocationCloudPipelineBuilderTests) passed 6 of 6, and CloudRequestEngineLiveTests ran 2 tests with 1 skipped, the license key test, as the full build has no license key for the cloud service. All ten Setting 'PullRequestSha' lines, one in Configure and one in each job, name ec978df, and Configure printed "Left out 6 macOS entries".

macOS was left out of this draft's full build under the 9 November decision. The rc head is built with macOS before it merges into main.

rc 1c99b72 is merged into this draft (merge commit ec978df, no conflicts), so the draft holds everything rc held then, #43 included. Between the first build and that merge, rc changed one line in each of three files in pipeline/pipeline.cloudrequestengine, two of them tests and the third Constants.java, where the configuration page link in a message changed (#115). The Cloud 51Did Tests workflow on the head, run 43594455688, ran the license key test with a license key set, and it passed with none skipped. rc has since gained #136 and #138, and a trial merge of b33daa0 into this head has no conflicts.

What #12 says that is now out of date

This draft closes #12, so the two statements in #12 that no longer hold are corrected here rather than left in the issue.

  1. Authenticate a Cloud Request Engine on a license key alone, and name the properties wanted #12's table marks "Resource key, Either, Property list Yes" as invalid, because "The service ignores the list". The specification now lists that combination as valid ("Each requested Property is added, as null with a reason where no licence grants it", in "Accepted combinations" linked above), and the engine builder on rc accepts it. This draft follows the specification.
  2. Authenticate a Cloud Request Engine on a license key alone, and name the properties wanted #12 says that accessibleproperties "answered 401 to a license key with no resource key", and point 5 of its "What to do" asks the engine to skip that request for a license key alone. Measured on 14 November 2026 in run 43535823198, the same request with the 51Did license key alone answered 200 and listed the license's product with its properties. The engine on rc (from Authenticate a Cloud Request Engine on a license key alone, and send the properties named #97) makes that request with the license key in the request body, and the live test builds such an engine and passes, so point 5 is not needed. This draft changes neither.

What remains

  1. The live test runs only where a license key for the cloud service is set, which today is the Cloud 51Did Tests workflow.
  2. The specification's "Properties the remote server did not return" still gives only the 21 September measurement. Adding the measurement above there changes nothing an engine must do, so this draft only records it, under "Measured while writing the live test".

A Pipeline built by the Device Detection, IP Intelligence or Location
cloud builder on a license key alone has to name the properties it
wants, and the builders have no way to give them. The tests build each
Pipeline against a fake cloud service and read the form it sends.
setRequestedProperties on CloudPipelineBuilderBase takes the fully
qualified property names, as a list or as comma separated text, and the
Device Detection, IP Intelligence and Location cloud builders pass them
to the Cloud Request Engine. A Pipeline can then authenticate on a
license key alone, which needs the properties named, and the message
that refuses a license key without them names a method the builder
has.
The Location cloud engine read the DelayExecution flag and the evidence
properties of each property the cloud service lists without allowing
for a property that has neither, so building its Pipeline stopped with
a NullPointerException. It now reads an absent flag as false and absent
evidence properties as none, as the cloud engine base class does.
…ey alone

The live test builds the engine with a license key and no resource key,
names a property the license grants, one every device data file has and
a name that is not a property, and checks that the service answers only
what was asked, that a property answered as null has its reason, and
that the engine reports the name left out once. It skips when no
license key for the cloud service is set. The Cloud 51Did workflow has
such a key, so it runs the test there.
@jwrosewell
jwrosewell marked this pull request as ready for review November 14, 2026 20:48
@jwrosewell
jwrosewell merged commit 20cadd0 into rc Nov 14, 2026
5 checks passed
@jwrosewell
jwrosewell deleted the feature/cloud-builders-requested-properties branch November 14, 2026 20:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant