Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ The tables below describe the examples available in this repository.
| Example | Description |
|--------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| GettingStarted (Console) | How to use the 51Degrees on-premise device detection API to determine details about a device based on its User-Agent and User-Agent Client Hints HTTP header values. |
| GettingStarted (Web) | How to use the 51Degrees Cloud service to determine details about a device as part of a simple Java servlet website. |
| GettingStarted (Web) | How to use the 51Degrees on-premise device detection API to determine details about a device as part of a simple Java servlet website. |
| Metadata | How to access the meta-data that relates to things like the properties populated device detection. |
| MatchMetrics | How to view metrics associated with the properties of processing with a Device Detection engine. |
| OfflineProcessing | Example showing how to ingest a file containing data from web requests and perform detection against the entries. |
Expand All @@ -101,6 +101,21 @@ Use them with relevant example class entrypoints like:
java -cp ./console/target/device-detection-java-examples.console-4.4.20-jar-with-dependencies.jar fiftyone.devicedetection.examples.console.OfflineProcessing
```

### Web examples

The web examples are run from the root of this repository, because they find their
web content by a path relative to it. They listen on port 8081 and stop when Enter
is pressed. Set the `PORT` environment variable to listen on another port, in which
case the example runs until the process is stopped:

```bash
PORT=8100 java -jar ./web/getting-started.onprem/target/device-detection-java-examples.web.getting-started.onprem-4.4.20-jar-with-dependencies.jar
```

The on-premise web example takes its data file from the `51DEGREES_DD_PATH`
environment variable, then from `TestDataFile`, and otherwise uses the free Lite file
in `device-detection-data`.

### Native library access

The on-premise examples use a native library, and
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@
* supplied filter which automatically creates and configures a device detection pipeline.
* <p>
* The configuration file for the pipeline is at src/main/webapp/WEB-INF/51Degrees-OnPrem.xml
* <p>
* The data file is taken from the 51DEGREES_DD_PATH environment variable, then
* from TestDataFile (an environment variable or system property), and otherwise
* the free Lite file in device-detection-data is used.
* <p>
* The server listens on port 8081 and stops when Enter is pressed. If the PORT
* environment variable is set, the server listens on that port instead and runs
* until the process is stopped, which is how automated tests start it.
*/
public class GettingStartedWebOnPrem extends HttpServlet {
private static final long serialVersionUID = 1734154705981153540L;
Expand All @@ -55,8 +63,15 @@ public static void main(String[] args) throws Exception {
configureLogback(getFilePath("logback.xml"));
logger.info("Running Example {}", GettingStartedWebOnPrem.class);

// start Jetty with this WebApp
EmbedJetty.runWebApp(resourceBase, 8081);
String portEnv = System.getenv("PORT");
if (portEnv != null) {
// Automated runs (e.g. the unified Selenium suite) inject a port and have no
// interactive stdin, so keep the server alive by joining it instead of waiting on Enter.
EmbedJetty.startWebApp(resourceBase, Integer.parseInt(portEnv)).join();
} else {
// start Jetty with this WebApp
EmbedJetty.runWebApp(resourceBase, 8081);
}
}

FlowDataProviderCore flowDataProvider = new FlowDataProviderCore.Default();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,12 @@
<BuildParameters>
<AutoUpdate>false</AutoUpdate>
<CreateTempDataCopy>false</CreateTempDataCopy>
<DataFile>${TestDataFile:-device-detection-data/51Degrees-LiteV4.1.hash}</DataFile>
<!--
The data file is taken from the 51DEGREES_DD_PATH environment
variable, then from TestDataFile (an environment variable or
system property), and otherwise the free Lite file is used.
-->
<DataFile>${51DEGREES_DD_PATH:-${TestDataFile:-device-detection-data/51Degrees-LiteV4.1.hash}}</DataFile>
<PerformanceProfile>LowMemory</PerformanceProfile>
</BuildParameters>
<BuilderName>DeviceDetectionHashEngine</BuilderName>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/* *********************************************************************
* This Original Work is copyright of 51 Degrees Mobile Experts Limited.
* Copyright 2026 51 Degrees Mobile Experts Limited, Davidson House,
* Forbury Square, Reading, Berkshire, United Kingdom RG1 3EU.
*
* This Original Work is licensed under the European Union Public Licence
* (EUPL) v.1.2 and is subject to its terms as set out below.
*
* If a copy of the EUPL was not distributed with this file, You can obtain
* one at https://opensource.org/licenses/EUPL-1.2.
*
* The 'Compatible Licences' set out in the Appendix to the EUPL (as may be
* amended by the European Commission) shall be deemed incompatible for
* the purposes of the Work and the provisions of the compatibility
* clause in Article 5 of the EUPL shall not apply.
*
* If using the Work as, or as part of, a network application, by
* including the attribution notice(s) required under Article 5 of the EUPL
* in the end user terms of the application under an appropriate heading,
* such notice(s) shall fulfill the requirements of that article.
* ********************************************************************* */

package fiftyone.devicedetection.examples.web;

import fiftyone.pipeline.core.configuration.PipelineOptions;
import fiftyone.pipeline.core.configuration.PipelineOptionsFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import static fiftyone.devicedetection.examples.web.GettingStartedWebOnPrem.resourceBase;
import static fiftyone.pipeline.util.FileFinder.getFilePath;
import static org.junit.Assert.assertEquals;
import static org.junit.Assume.assumeTrue;

/**
* Checks the order in which the on-premise web example picks its data file,
* being 51DEGREES_DD_PATH first, then TestDataFile, then the Lite file.
* System properties stand in for the environment variables, because the
* lookup reads either and a test cannot set an environment variable.
*/
public class OnPremDataFileOptionTest {
private static final String DD_PATH = "51DEGREES_DD_PATH";
private static final String TEST_DATA_FILE = "TestDataFile";
private static final String LITE =
"device-detection-data/51Degrees-LiteV4.1.hash";

private String savedDdPath;
private String savedTestDataFile;

@Before
public void saveProperties() {
// An environment variable of either name would take precedence over
// the system properties set here, so the test cannot run.
assumeTrue(System.getenv(DD_PATH) == null);
assumeTrue(System.getenv(TEST_DATA_FILE) == null);
assumeTrue(System.getenv(TEST_DATA_FILE.toUpperCase()) == null);
savedDdPath = System.getProperty(DD_PATH);
savedTestDataFile = System.getProperty(TEST_DATA_FILE);
System.clearProperty(DD_PATH);
System.clearProperty(TEST_DATA_FILE);
}

@After
public void restoreProperties() {
restore(DD_PATH, savedDdPath);
restore(TEST_DATA_FILE, savedTestDataFile);
}

@Test
public void usesLiteWhenNothingIsSet() throws Exception {
assertEquals(LITE, dataFile());
}

@Test
public void usesTestDataFileWhenOnlyThatIsSet() throws Exception {
System.setProperty(TEST_DATA_FILE, "from-test-data-file.hash");
assertEquals("from-test-data-file.hash", dataFile());
}

@Test
public void prefersDdPathOverTestDataFile() throws Exception {
System.setProperty(TEST_DATA_FILE, "from-test-data-file.hash");
System.setProperty(DD_PATH, "from-dd-path.hash");
assertEquals("from-dd-path.hash", dataFile());
}

private static String dataFile() throws Exception {
PipelineOptions options = PipelineOptionsFactory.getOptionsFromFile(
getFilePath(resourceBase) + "/WEB-INF/51Degrees-OnPrem.xml");
return options.findAndSubstitute("DeviceDetectionHashEngine", "DataFile");
}

private static void restore(String name, String value) {
if (value == null) {
System.clearProperty(name);
} else {
System.setProperty(name, value);
}
}
}
Loading