From 33a3d78ff321340def2d7ce2667b6ea8ae23b05c Mon Sep 17 00:00:00 2001 From: Victor Benarbia Date: Sat, 3 Jan 2026 21:52:59 -0600 Subject: [PATCH 01/11] Update project to Java 21, Gradle 8.5, and modernize CI/CD Summary of changes: - Upgraded Java target to version 21. - Updated Gradle wrapper to version 8.5 for Java 21 compatibility. - Refactored SerpApi.java to remove incorrect inheritance from Exception. - Updated GitHub Actions workflow to use Java 21 and gradle-setup-java action. - Switched environment variable for API keys to SERPAPI_KEY in tests and CI. - Reorganized tests: moved engine examples to src/test/java/serpapi/example/. - Fixed failures in LocationApiTest and GoogleReverseImageTest. --- .github/workflows/gradle.yml | 13 +- LICENSE | 2 +- README.md | 2 +- README.md.erb | 2 +- build.gradle | 8 +- demo/Makefile | 6 +- demo/build.gradle | 3 + gradle/wrapper/gradle-wrapper.properties | 2 +- src/main/java/serpapi/SerpApi.java | 2 +- src/test/java/basic_search_result.json | 175 ------------------ src/test/java/serpapi/AccountApiTest.java | 4 +- src/test/java/serpapi/LocationApiTest.java | 4 +- src/test/java/serpapi/SearchApiTest.java | 41 ++++ ...ApiTest.java => SearchArchiveApiTest.java} | 29 +-- .../{ => example}/AppleAppStoreTest.java | 4 +- .../java/serpapi/{ => example}/BaiduTest.java | 4 +- .../java/serpapi/{ => example}/BingTest.java | 4 +- .../serpapi/{ => example}/DuckduckgoTest.java | 4 +- .../java/serpapi/{ => example}/EbayTest.java | 4 +- .../{ => example}/GoogleAutocompleteTest.java | 4 +- .../{ => example}/GoogleEventsTest.java | 4 +- .../{ => example}/GoogleImagesTest.java | 4 +- .../serpapi/{ => example}/GoogleJobsTest.java | 4 +- .../GoogleLocalServicesTest.java | 4 +- .../serpapi/{ => example}/GoogleMapsTest.java | 4 +- .../serpapi/{ => example}/GooglePlayTest.java | 4 +- .../{ => example}/GoogleProductTest.java | 4 +- .../{ => example}/GoogleReverseImageTest.java | 7 +- .../{ => example}/GoogleScholarTest.java | 4 +- .../serpapi/{ => example}/GoogleTest.java | 4 +- .../serpapi/{ => example}/HomeDepotTest.java | 4 +- .../java/serpapi/{ => example}/NaverTest.java | 4 +- .../serpapi/{ => example}/WalmartTest.java | 4 +- .../java/serpapi/{ => example}/YahooTest.java | 4 +- .../serpapi/{ => example}/YoutubeTest.java | 4 +- 35 files changed, 115 insertions(+), 265 deletions(-) delete mode 100644 src/test/java/basic_search_result.json create mode 100644 src/test/java/serpapi/SearchApiTest.java rename src/test/java/serpapi/{SerpApiTest.java => SearchArchiveApiTest.java} (60%) rename src/test/java/serpapi/{ => example}/AppleAppStoreTest.java (88%) rename src/test/java/serpapi/{ => example}/BaiduTest.java (88%) rename src/test/java/serpapi/{ => example}/BingTest.java (88%) rename src/test/java/serpapi/{ => example}/DuckduckgoTest.java (88%) rename src/test/java/serpapi/{ => example}/EbayTest.java (88%) rename src/test/java/serpapi/{ => example}/GoogleAutocompleteTest.java (88%) rename src/test/java/serpapi/{ => example}/GoogleEventsTest.java (88%) rename src/test/java/serpapi/{ => example}/GoogleImagesTest.java (89%) rename src/test/java/serpapi/{ => example}/GoogleJobsTest.java (88%) rename src/test/java/serpapi/{ => example}/GoogleLocalServicesTest.java (89%) rename src/test/java/serpapi/{ => example}/GoogleMapsTest.java (89%) rename src/test/java/serpapi/{ => example}/GooglePlayTest.java (88%) rename src/test/java/serpapi/{ => example}/GoogleProductTest.java (89%) rename src/test/java/serpapi/{ => example}/GoogleReverseImageTest.java (77%) rename src/test/java/serpapi/{ => example}/GoogleScholarTest.java (88%) rename src/test/java/serpapi/{ => example}/GoogleTest.java (88%) rename src/test/java/serpapi/{ => example}/HomeDepotTest.java (88%) rename src/test/java/serpapi/{ => example}/NaverTest.java (88%) rename src/test/java/serpapi/{ => example}/WalmartTest.java (88%) rename src/test/java/serpapi/{ => example}/YahooTest.java (88%) rename src/test/java/serpapi/{ => example}/YoutubeTest.java (88%) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 27c7871..95f5b44 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -15,14 +15,17 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: Set up JDK 1.8 - uses: actions/setup-java@v1 + - uses: actions/checkout@v4 + - name: Set up JDK 21 + uses: actions/setup-java@v4 with: - java-version: 1.8 + java-version: '21' + distribution: 'temurin' - name: Grant execute permission for gradlew run: chmod +x gradlew + - name: Build with Gradle + uses: gradle/actions/setup-gradle@v3 - name: test run: ./gradlew test env: - API_KEY: ${{secrets.API_KEY}} \ No newline at end of file + SERPAPI_KEY: ${{secrets.SERPAPI_KEY}} \ No newline at end of file diff --git a/LICENSE b/LICENSE index 5d31a9d..fd42aa3 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2018-2024 SerpApi +Copyright (c) 2018-2025 SerpApi Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 4e46957..22a91cc 100644 --- a/README.md +++ b/README.md @@ -123,7 +123,7 @@ it prints the first 3 location matching Austin (Texas, Texas, Rochester) Let's run a search to get a search_id. ```java Map auth = new HashMap<>(); -auth.put("api_key", System.getenv("API_KEY")); +auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi serpapi = new SerpApi(auth); Map parameter = new HashMap<>(); diff --git a/README.md.erb b/README.md.erb index 2a33cfe..ffea8d7 100644 --- a/README.md.erb +++ b/README.md.erb @@ -135,7 +135,7 @@ it prints the first 3 location matching Austin (Texas, Texas, Rochester) Let's run a search to get a search_id. ```java Map auth = new HashMap<>(); -auth.put("api_key", System.getenv("API_KEY")); +auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi serpapi = new SerpApi(auth); Map parameter = new HashMap<>(); diff --git a/build.gradle b/build.gradle index ec29b8e..7ac1980 100644 --- a/build.gradle +++ b/build.gradle @@ -9,12 +9,12 @@ plugins { // Package default archivesBaseName = 'serpapi' -version = '1.0.0' +version = '1.1.0' group = 'com.github.serpapi' // java version -sourceCompatibility = 1.8 -targetCompatibility = 1.8 +sourceCompatibility = 21 +targetCompatibility = 21 // Load repositories repositories { @@ -65,6 +65,6 @@ publishing { } wrapper { - gradleVersion = "7.3.3" + gradleVersion = "8.5" distributionType = Wrapper.DistributionType.ALL } diff --git a/demo/Makefile b/demo/Makefile index e4c2ab5..a98d3b8 100644 --- a/demo/Makefile +++ b/demo/Makefile @@ -1,9 +1,9 @@ .PHONY: build -ifndef API_KEY -$(error "API_KEY must be defined") +ifndef SERPAPI_KEY +$(error "SERPAPI_KEY must be defined") else -$(info "found API_KEY variable") +$(info "found SERPAPI_KEY variable") endif all: init clean build run diff --git a/demo/build.gradle b/demo/build.gradle index 321c5da..7f4da8e 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -14,6 +14,9 @@ plugins { id 'application' } +sourceCompatibility = 21 +targetCompatibility = 21 + repositories { mavenCentral() diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 669386b..d0d403e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/serpapi/SerpApi.java b/src/main/java/serpapi/SerpApi.java index 9b2f79c..3a0f425 100644 --- a/src/main/java/serpapi/SerpApi.java +++ b/src/main/java/serpapi/SerpApi.java @@ -11,7 +11,7 @@ /** * SerpApi wraps HTTP interaction with the service serpapi.com */ -public class SerpApi extends Exception { +public class SerpApi { /** * client parameters diff --git a/src/test/java/basic_search_result.json b/src/test/java/basic_search_result.json deleted file mode 100644 index d2dd85b..0000000 --- a/src/test/java/basic_search_result.json +++ /dev/null @@ -1,175 +0,0 @@ -{ - "search_metadata": { - "id": "5c91926661a1347a7a2ebe3a", - "status": "Success", - "created_at": "2019-03-20 01:07:50 UTC", - "processed_at": "2019-03-20 01:07:50 UTC", - "google_url": "https://www.google.com/search?q=Coffee&oq=Coffee&uule=w+CAIQICIaQXVzdGluLFRleGFzLFVuaXRlZCBTdGF0ZXM&hl=en&gl=us&num=10&safe=active&start=10&sourceid=chrome&ie=UTF-8", - "total_time_taken": 10.29 - }, - "search_parameters": { - "q": "Coffee", - "location_requested": "Austin, Texas, United States", - "location_used": "Austin,Texas,United States", - "google_domain": "google.com", - "hl": "en", - "gl": "us", - "safe": "active", - "start": "10", - "device": "desktop" - }, - "search_information": { - "total_results": 23620000000, - "time_taken_displayed": 0.6, - "query_displayed": "Coffee" - }, - "organic_results": [ - { - "position": 1, - "title": "What is Coffee? - National Coffee Association", - "link": "http://www.ncausa.org/about-coffee/what-is-coffee", - "displayed_link": "www.ncausa.org › About Coffee › What is Coffee?", - "snippet": "Coffee trees are pruned short to conserve their energy and aid in harvesting, but can grow to more than 30 feet (9 meters) high. Each tree is covered with green, ...", - "cached_page_link": "http://webcache.googleusercontent.com/search?q=cache:eukMDyc_TlwJ:www.ncausa.org/about-coffee/what-is-coffee+&cd=11&hl=en&ct=clnk&gl=us" - }, - { - "position": 2, - "title": "The History of Coffee - National Coffee Association", - "link": "http://www.ncausa.org/about-coffee/history-of-coffee", - "displayed_link": "www.ncausa.org › About Coffee › History of Coffee", - "snippet": "No one knows exactly how or when coffee was discovered, though there are many legends about its origin. ... Coffee grown worldwide can trace its heritage back centuries to the ancient coffee forests on the Ethiopian plateau. There, legend says the goat herder Kaldi first discovered the ...", - "cached_page_link": "http://webcache.googleusercontent.com/search?q=cache:lVL_jlE3B80J:www.ncausa.org/about-coffee/history-of-coffee+&cd=12&hl=en&ct=clnk&gl=us" - }, - { - "position": 3, - "title": "The Coffee House « Austin Improv Comedy Shows, Classes – The ...", - "link": "http://www.hideouttheatre.com/coffeehouse", - "displayed_link": "www.hideouttheatre.com/coffeehouse", - "snippet": "The Hideout is downtown Austin's oldest independent coffee house. We are open morning to night, weekdays and weekends and serve beer, wine, fresh ...", - "cached_page_link": "http://webcache.googleusercontent.com/search?q=cache:VD32HaeikQMJ:www.hideouttheatre.com/coffeehouse+&cd=13&hl=en&ct=clnk&gl=us", - "related_pages_link": "https://www.google.com/search?safe=active&gl=us&hl=en&q=related:www.hideouttheatre.com/coffeehouse+Coffee&tbo=1&sa=X&ved=2ahUKEwigrp6FxI_hAhVN4qwKHZzvA9s4ChAfMAJ6BAgJEAU", - "rich_snippet": { - "bottom": { - "extensions": [ - "Thu, Mar 21", - "PGraph", - "Thu, Mar 21", - "Austin Secrets", - "Thu, Mar 21", - "The Free Fringe" - ] - } - } - }, - { - "position": 4, - "title": "Home | The Coffee Bean & Tea Leaf", - "link": "https://www.coffeebean.com/", - "displayed_link": "https://www.coffeebean.com/", - "snippet": "Never run out of your favorite coffees, teas and powders again with our auto-delivery subscription. Select how often your products arrive, pause and cancel ...", - "cached_page_link": "https://webcache.googleusercontent.com/search?q=cache:WpQxSYo2c6AJ:https://www.coffeebean.com/+&cd=14&hl=en&ct=clnk&gl=us", - "related_pages_link": "https://www.google.com/search?safe=active&gl=us&hl=en&q=related:https://www.coffeebean.com/+Coffee&tbo=1&sa=X&ved=2ahUKEwigrp6FxI_hAhVN4qwKHZzvA9s4ChAfMAN6BAgFEAU" - }, - { - "position": 5, - "title": "Coffee Review - The World's Leading Coffee Guide", - "link": "https://www.coffeereview.com/", - "displayed_link": "https://www.coffeereview.com/", - "snippet": "Coffee reviews, espresso ratings, informative articles, and coffee blogs by Kenneth Davids and other coffee experts.", - "cached_page_link": "https://webcache.googleusercontent.com/search?q=cache:c9jncvPT1SsJ:https://www.coffeereview.com/+&cd=15&hl=en&ct=clnk&gl=us" - }, - { - "position": 6, - "title": "Coffee: Benefits, nutrition, and risks - Medical News Today", - "link": "https://www.medicalnewstoday.com/articles/270202.php", - "displayed_link": "https://www.medicalnewstoday.com/articles/270202.php", - "date": "Dec 14, 2017", - "snippet": "Drinking coffee may do much more than simply provide an energy boost when needed. Several scientific studies have identified a number of ...", - "cached_page_link": "https://webcache.googleusercontent.com/search?q=cache:FB_36c_qnUAJ:https://www.medicalnewstoday.com/articles/270202.php+&cd=16&hl=en&ct=clnk&gl=us" - }, - { - "position": 7, - "title": "Peet's Coffee: The Original Craft Coffee", - "link": "https://www.peets.com/", - "displayed_link": "https://www.peets.com/", - "snippet": "Since 1966, Peet's Coffee has offered superior coffees and teas by sourcing the best quality coffee beans and tea leaves in the world and adhering to strict ...", - "cached_page_link": "https://webcache.googleusercontent.com/search?q=cache:BCjzno6zP6wJ:https://www.peets.com/+&cd=17&hl=en&ct=clnk&gl=us", - "related_pages_link": "https://www.google.com/search?safe=active&gl=us&hl=en&q=related:https://www.peets.com/+Coffee&tbo=1&sa=X&ved=2ahUKEwigrp6FxI_hAhVN4qwKHZzvA9s4ChAfMAZ6BAgGEAU" - }, - { - "position": 8, - "title": "The Best Coffee from Starbucks Coffee", - "link": "https://www.starbucks.com/coffee", - "displayed_link": "https://www.starbucks.com/coffee", - "snippet": "Next stop: Asia / Pacific. Journey through the world's coffee regions with our Passport Series—coffee selected to give you a sense of place. Now we're visiting ...", - "cached_page_link": "https://webcache.googleusercontent.com/search?q=cache:R7fHYjcarfsJ:https://www.starbucks.com/coffee+&cd=18&hl=en&ct=clnk&gl=us", - "related_pages_link": "https://www.google.com/search?safe=active&gl=us&hl=en&q=related:https://www.starbucks.com/coffee+Coffee&tbo=1&sa=X&ved=2ahUKEwigrp6FxI_hAhVN4qwKHZzvA9s4ChAfMAd6BAgHEAU" - }, - { - "position": 9, - "title": "Seventh Flag Coffee - Austin", - "link": "http://www.seventhflagcoffee.com/", - "displayed_link": "www.seventhflagcoffee.com/", - "snippet": "Seventh Flag Coffee Co. is dedicated to creating the best overall coffee experience for every customer that walks through our doors. We are transforming the ...", - "cached_page_link": "http://webcache.googleusercontent.com/search?q=cache:VZCbBEneWWkJ:www.seventhflagcoffee.com/+&cd=19&hl=en&ct=clnk&gl=us", - "related_pages_link": "https://www.google.com/search?safe=active&gl=us&hl=en&q=related:www.seventhflagcoffee.com/+Coffee&tbo=1&sa=X&ved=2ahUKEwigrp6FxI_hAhVN4qwKHZzvA9s4ChAfMAh6BAgIEAU" - }, - { - "position": 10, - "title": "Cosmic Coffee + Beer Garden - Austin, Tx", - "link": "https://www.cosmiccoffeebeer.com/", - "displayed_link": "https://www.cosmiccoffeebeer.com/", - "snippet": "specialty coffee, craft cocktails, locally brewed beer, food trailers and live music in a permaculture inspired garden setting in south austin, tx.", - "cached_page_link": "https://webcache.googleusercontent.com/search?q=cache:tsOR-R1-gmQJ:https://www.cosmiccoffeebeer.com/+&cd=20&hl=en&ct=clnk&gl=us" - } - ], - "related_searches": [ - { - "query": "mozarts coffee", - "link": "https://www.google.com/search?safe=active&gl=us&hl=en&q=mozarts+coffee&sa=X&ved=2ahUKEwigrp6FxI_hAhVN4qwKHZzvA9s4ChDVAigAegQIChAB" - }, - { - "query": "bennu coffee", - "link": "https://www.google.com/search?safe=active&gl=us&hl=en&q=bennu+coffee&sa=X&ved=2ahUKEwigrp6FxI_hAhVN4qwKHZzvA9s4ChDVAigBegQIChAC" - }, - { - "query": "coffee near me", - "link": "https://www.google.com/search?safe=active&gl=us&hl=en&q=coffee+near+me&sa=X&ved=2ahUKEwigrp6FxI_hAhVN4qwKHZzvA9s4ChDVAigCegQIChAD" - }, - { - "query": "coffee austin", - "link": "https://www.google.com/search?safe=active&gl=us&hl=en&q=coffee+austin&sa=X&ved=2ahUKEwigrp6FxI_hAhVN4qwKHZzvA9s4ChDVAigDegQIChAE" - }, - { - "query": "best coffee in austin", - "link": "https://www.google.com/search?safe=active&gl=us&hl=en&q=best+coffee+in+austin&sa=X&ved=2ahUKEwigrp6FxI_hAhVN4qwKHZzvA9s4ChDVAigEegQIChAF" - }, - { - "query": "coffee shops near me", - "link": "https://www.google.com/search?safe=active&gl=us&hl=en&q=coffee+shops+near+me&sa=X&ved=2ahUKEwigrp6FxI_hAhVN4qwKHZzvA9s4ChDVAigFegQIChAG" - }, - { - "query": "houndstooth coffee", - "link": "https://www.google.com/search?safe=active&gl=us&hl=en&q=houndstooth+coffee&sa=X&ved=2ahUKEwigrp6FxI_hAhVN4qwKHZzvA9s4ChDVAigGegQIChAH" - }, - { - "query": "epoch coffee", - "link": "https://www.google.com/search?safe=active&gl=us&hl=en&q=epoch+coffee&sa=X&ved=2ahUKEwigrp6FxI_hAhVN4qwKHZzvA9s4ChDVAigHegQIChAI" - } - ], - "pagination": { - "current": 2, - "next": "https://www.google.com/search?q=Coffee&safe=active&gl=us&hl=en&ei=b5KRXOC6Bc3EswWc34_YDQ&start=20&sa=N&ved=0ahUKEwigrp6FxI_hAhVN4qwKHZzvA9s4ChDw0wMIjAE", - "other_pages": { - "1": "https://www.google.com/search?q=Coffee&safe=active&gl=us&hl=en&ei=b5KRXOC6Bc3EswWc34_YDQ&start=0&sa=N&ved=0ahUKEwigrp6FxI_hAhVN4qwKHZzvA9s4ChDy0wMIeQ", - "3": "https://www.google.com/search?q=Coffee&safe=active&gl=us&hl=en&ei=b5KRXOC6Bc3EswWc34_YDQ&start=20&sa=N&ved=0ahUKEwigrp6FxI_hAhVN4qwKHZzvA9s4ChDy0wMIfA", - "4": "https://www.google.com/search?q=Coffee&safe=active&gl=us&hl=en&ei=b5KRXOC6Bc3EswWc34_YDQ&start=30&sa=N&ved=0ahUKEwigrp6FxI_hAhVN4qwKHZzvA9s4ChDy0wMIfg", - "5": "https://www.google.com/search?q=Coffee&safe=active&gl=us&hl=en&ei=b5KRXOC6Bc3EswWc34_YDQ&start=40&sa=N&ved=0ahUKEwigrp6FxI_hAhVN4qwKHZzvA9s4ChDy0wMIgAE", - "6": "https://www.google.com/search?q=Coffee&safe=active&gl=us&hl=en&ei=b5KRXOC6Bc3EswWc34_YDQ&start=50&sa=N&ved=0ahUKEwigrp6FxI_hAhVN4qwKHZzvA9s4ChDy0wMIggE", - "7": "https://www.google.com/search?q=Coffee&safe=active&gl=us&hl=en&ei=b5KRXOC6Bc3EswWc34_YDQ&start=60&sa=N&ved=0ahUKEwigrp6FxI_hAhVN4qwKHZzvA9s4ChDy0wMIhAE", - "8": "https://www.google.com/search?q=Coffee&safe=active&gl=us&hl=en&ei=b5KRXOC6Bc3EswWc34_YDQ&start=70&sa=N&ved=0ahUKEwigrp6FxI_hAhVN4qwKHZzvA9s4ChDy0wMIhgE", - "9": "https://www.google.com/search?q=Coffee&safe=active&gl=us&hl=en&ei=b5KRXOC6Bc3EswWc34_YDQ&start=80&sa=N&ved=0ahUKEwigrp6FxI_hAhVN4qwKHZzvA9s4ChDy0wMIiAE", - "10": "https://www.google.com/search?q=Coffee&safe=active&gl=us&hl=en&ei=b5KRXOC6Bc3EswWc34_YDQ&start=90&sa=N&ved=0ahUKEwigrp6FxI_hAhVN4qwKHZzvA9s4ChDy0wMIigE" - } - } -} \ No newline at end of file diff --git a/src/test/java/serpapi/AccountApiTest.java b/src/test/java/serpapi/AccountApiTest.java index cb49d6d..8ca2778 100644 --- a/src/test/java/serpapi/AccountApiTest.java +++ b/src/test/java/serpapi/AccountApiTest.java @@ -16,12 +16,12 @@ public class AccountApiTest { @Test public void account() throws Exception { - if (System.getenv("API_KEY") == null) { + if (System.getenv("SERPAPI_KEY") == null) { return; } Map parameter = new HashMap(); - parameter.put("api_key", System.getenv("API_KEY")); + parameter.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(parameter); JsonObject info = client.account(); System.out.println(info.toString()); diff --git a/src/test/java/serpapi/LocationApiTest.java b/src/test/java/serpapi/LocationApiTest.java index 35ca1e9..1b0915d 100644 --- a/src/test/java/serpapi/LocationApiTest.java +++ b/src/test/java/serpapi/LocationApiTest.java @@ -17,13 +17,13 @@ public class LocationApiTest { @Test public void location() throws Exception { - if(System.getenv("API_KEY") == null) + if(System.getenv("SERPAPI_KEY") == null) return; SerpApi serpapi = new SerpApi(); Map parameter = new HashMap(); - parameter.put("q", "Austin"); + parameter.put("q", "Austin, TX"); parameter.put("limit", "3"); JsonArray location = serpapi.location(parameter); assertEquals("Austin, TX", location.get(0).getAsJsonObject().get("name").getAsString()); diff --git a/src/test/java/serpapi/SearchApiTest.java b/src/test/java/serpapi/SearchApiTest.java new file mode 100644 index 0000000..7109619 --- /dev/null +++ b/src/test/java/serpapi/SearchApiTest.java @@ -0,0 +1,41 @@ +package serpapi; + +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.*; + +/** + * Test main class + */ +public class SearchApiTest { + + @Test + public void search() throws SerpApiException, InterruptedException { + // skip test if no api_key provided + if(System.getenv("SERPAPI_KEY") == null) + return; + + Map auth = new HashMap<>(); + auth.put("api_key", System.getenv("SERPAPI_KEY")); + SerpApi serpapi = new SerpApi(auth); + + Map parameter = new HashMap<>(); + parameter.put("q", "Coffee"); + parameter.put("location", "Austin, Texas, United States"); + parameter.put("hl", "en"); + parameter.put("gl", "us"); + parameter.put("google_domain", "google.com"); + parameter.put("safe", "active"); + parameter.put("start", "10"); + parameter.put("device", "desktop"); + + JsonObject results = serpapi.search(parameter); + assertTrue(results.getAsJsonArray("organic_results").size() > 5); + } + +} diff --git a/src/test/java/serpapi/SerpApiTest.java b/src/test/java/serpapi/SearchArchiveApiTest.java similarity index 60% rename from src/test/java/serpapi/SerpApiTest.java rename to src/test/java/serpapi/SearchArchiveApiTest.java index 4abc9bd..c1e5e99 100644 --- a/src/test/java/serpapi/SerpApiTest.java +++ b/src/test/java/serpapi/SearchArchiveApiTest.java @@ -12,40 +12,17 @@ /** * Test main class */ -public class SerpApiTest { +public class SearchArchiveApiTest { - @Test - public void search() throws SerpApiException, InterruptedException { - // skip test if no api_key provided - if(System.getenv("API_KEY") == null) - return; - - Map auth = new HashMap<>(); - auth.put("api_key", System.getenv("API_KEY")); - SerpApi serpapi = new SerpApi(auth); - - Map parameter = new HashMap<>(); - parameter.put("q", "Coffee"); - parameter.put("location", "Austin, Texas, United States"); - parameter.put("hl", "en"); - parameter.put("gl", "us"); - parameter.put("google_domain", "google.com"); - parameter.put("safe", "active"); - parameter.put("start", "10"); - parameter.put("device", "desktop"); - - JsonObject results = serpapi.search(parameter); - assertTrue(results.getAsJsonArray("organic_results").size() > 5); - } @Test public void searchArchive() throws SerpApiException, InterruptedException { // skip test if no api_key provided - if(System.getenv("API_KEY") == null) + if(System.getenv("SERPAPI_KEY") == null) return; Map parameter = new HashMap<>(); - parameter.put("api_key", System.getenv("API_KEY")); + parameter.put("api_key", System.getenv("SERPAPI_KEY")); parameter.put("q", "Coffee"); parameter.put("location", "Austin, Texas, United States"); parameter.put("hl", "en"); diff --git a/src/test/java/serpapi/AppleAppStoreTest.java b/src/test/java/serpapi/example/AppleAppStoreTest.java similarity index 88% rename from src/test/java/serpapi/AppleAppStoreTest.java rename to src/test/java/serpapi/example/AppleAppStoreTest.java index a8d5708..a1af4f5 100644 --- a/src/test/java/serpapi/AppleAppStoreTest.java +++ b/src/test/java/serpapi/example/AppleAppStoreTest.java @@ -17,12 +17,12 @@ public class AppleAppStoreTest { @Test public void search() throws SerpApiException { // skip test if no api_key provided - if(System.getenv("API_KEY") == null) + if(System.getenv("SERPAPI_KEY") == null) return; // setup serpapi client Map auth = new HashMap<>(); - auth.put("api_key", System.getenv("API_KEY")); + auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search diff --git a/src/test/java/serpapi/BaiduTest.java b/src/test/java/serpapi/example/BaiduTest.java similarity index 88% rename from src/test/java/serpapi/BaiduTest.java rename to src/test/java/serpapi/example/BaiduTest.java index 8cbee14..cea68d7 100644 --- a/src/test/java/serpapi/BaiduTest.java +++ b/src/test/java/serpapi/example/BaiduTest.java @@ -17,12 +17,12 @@ public class BaiduTest { @Test public void search() throws SerpApiException { // skip test if no api_key provided - if(System.getenv("API_KEY") == null) + if(System.getenv("SERPAPI_KEY") == null) return; // setup serpapi client Map auth = new HashMap<>(); - auth.put("api_key", System.getenv("API_KEY")); + auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search diff --git a/src/test/java/serpapi/BingTest.java b/src/test/java/serpapi/example/BingTest.java similarity index 88% rename from src/test/java/serpapi/BingTest.java rename to src/test/java/serpapi/example/BingTest.java index defc69e..6adacf7 100644 --- a/src/test/java/serpapi/BingTest.java +++ b/src/test/java/serpapi/example/BingTest.java @@ -17,12 +17,12 @@ public class BingTest { @Test public void search() throws SerpApiException { // skip test if no api_key provided - if(System.getenv("API_KEY") == null) + if(System.getenv("SERPAPI_KEY") == null) return; // setup serpapi client Map auth = new HashMap<>(); - auth.put("api_key", System.getenv("API_KEY")); + auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search diff --git a/src/test/java/serpapi/DuckduckgoTest.java b/src/test/java/serpapi/example/DuckduckgoTest.java similarity index 88% rename from src/test/java/serpapi/DuckduckgoTest.java rename to src/test/java/serpapi/example/DuckduckgoTest.java index 22d9cee..5a5ba47 100644 --- a/src/test/java/serpapi/DuckduckgoTest.java +++ b/src/test/java/serpapi/example/DuckduckgoTest.java @@ -17,12 +17,12 @@ public class DuckduckgoTest { @Test public void search() throws SerpApiException { // skip test if no api_key provided - if(System.getenv("API_KEY") == null) + if(System.getenv("SERPAPI_KEY") == null) return; // setup serpapi client Map auth = new HashMap<>(); - auth.put("api_key", System.getenv("API_KEY")); + auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search diff --git a/src/test/java/serpapi/EbayTest.java b/src/test/java/serpapi/example/EbayTest.java similarity index 88% rename from src/test/java/serpapi/EbayTest.java rename to src/test/java/serpapi/example/EbayTest.java index facdf60..874f48e 100644 --- a/src/test/java/serpapi/EbayTest.java +++ b/src/test/java/serpapi/example/EbayTest.java @@ -17,12 +17,12 @@ public class EbayTest { @Test public void search() throws SerpApiException { // skip test if no api_key provided - if(System.getenv("API_KEY") == null) + if(System.getenv("SERPAPI_KEY") == null) return; // setup serpapi client Map auth = new HashMap<>(); - auth.put("api_key", System.getenv("API_KEY")); + auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search diff --git a/src/test/java/serpapi/GoogleAutocompleteTest.java b/src/test/java/serpapi/example/GoogleAutocompleteTest.java similarity index 88% rename from src/test/java/serpapi/GoogleAutocompleteTest.java rename to src/test/java/serpapi/example/GoogleAutocompleteTest.java index b2f9518..a279363 100644 --- a/src/test/java/serpapi/GoogleAutocompleteTest.java +++ b/src/test/java/serpapi/example/GoogleAutocompleteTest.java @@ -17,12 +17,12 @@ public class GoogleAutocompleteTest { @Test public void search() throws SerpApiException { // skip test if no api_key provided - if(System.getenv("API_KEY") == null) + if(System.getenv("SERPAPI_KEY") == null) return; // setup serpapi client Map auth = new HashMap<>(); - auth.put("api_key", System.getenv("API_KEY")); + auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search diff --git a/src/test/java/serpapi/GoogleEventsTest.java b/src/test/java/serpapi/example/GoogleEventsTest.java similarity index 88% rename from src/test/java/serpapi/GoogleEventsTest.java rename to src/test/java/serpapi/example/GoogleEventsTest.java index ffddcaf..df46c1a 100644 --- a/src/test/java/serpapi/GoogleEventsTest.java +++ b/src/test/java/serpapi/example/GoogleEventsTest.java @@ -17,12 +17,12 @@ public class GoogleEventsTest { @Test public void search() throws SerpApiException { // skip test if no api_key provided - if(System.getenv("API_KEY") == null) + if(System.getenv("SERPAPI_KEY") == null) return; // setup serpapi client Map auth = new HashMap<>(); - auth.put("api_key", System.getenv("API_KEY")); + auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search diff --git a/src/test/java/serpapi/GoogleImagesTest.java b/src/test/java/serpapi/example/GoogleImagesTest.java similarity index 89% rename from src/test/java/serpapi/GoogleImagesTest.java rename to src/test/java/serpapi/example/GoogleImagesTest.java index a2c9932..cf27d53 100644 --- a/src/test/java/serpapi/GoogleImagesTest.java +++ b/src/test/java/serpapi/example/GoogleImagesTest.java @@ -17,12 +17,12 @@ public class GoogleImagesTest { @Test public void search() throws SerpApiException { // skip test if no api_key provided - if(System.getenv("API_KEY") == null) + if(System.getenv("SERPAPI_KEY") == null) return; // setup serpapi client Map auth = new HashMap<>(); - auth.put("api_key", System.getenv("API_KEY")); + auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search diff --git a/src/test/java/serpapi/GoogleJobsTest.java b/src/test/java/serpapi/example/GoogleJobsTest.java similarity index 88% rename from src/test/java/serpapi/GoogleJobsTest.java rename to src/test/java/serpapi/example/GoogleJobsTest.java index 9bc5a85..eb274c2 100644 --- a/src/test/java/serpapi/GoogleJobsTest.java +++ b/src/test/java/serpapi/example/GoogleJobsTest.java @@ -17,12 +17,12 @@ public class GoogleJobsTest { @Test public void search() throws SerpApiException { // skip test if no api_key provided - if(System.getenv("API_KEY") == null) + if(System.getenv("SERPAPI_KEY") == null) return; // setup serpapi client Map auth = new HashMap<>(); - auth.put("api_key", System.getenv("API_KEY")); + auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search diff --git a/src/test/java/serpapi/GoogleLocalServicesTest.java b/src/test/java/serpapi/example/GoogleLocalServicesTest.java similarity index 89% rename from src/test/java/serpapi/GoogleLocalServicesTest.java rename to src/test/java/serpapi/example/GoogleLocalServicesTest.java index f0cc543..b3574d4 100644 --- a/src/test/java/serpapi/GoogleLocalServicesTest.java +++ b/src/test/java/serpapi/example/GoogleLocalServicesTest.java @@ -17,12 +17,12 @@ public class GoogleLocalServicesTest { @Test public void search() throws SerpApiException { // skip test if no api_key provided - if(System.getenv("API_KEY") == null) + if(System.getenv("SERPAPI_KEY") == null) return; // setup serpapi client Map auth = new HashMap<>(); - auth.put("api_key", System.getenv("API_KEY")); + auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search diff --git a/src/test/java/serpapi/GoogleMapsTest.java b/src/test/java/serpapi/example/GoogleMapsTest.java similarity index 89% rename from src/test/java/serpapi/GoogleMapsTest.java rename to src/test/java/serpapi/example/GoogleMapsTest.java index 0e6ac43..37ea934 100644 --- a/src/test/java/serpapi/GoogleMapsTest.java +++ b/src/test/java/serpapi/example/GoogleMapsTest.java @@ -17,12 +17,12 @@ public class GoogleMapsTest { @Test public void search() throws SerpApiException { // skip test if no api_key provided - if(System.getenv("API_KEY") == null) + if(System.getenv("SERPAPI_KEY") == null) return; // setup serpapi client Map auth = new HashMap<>(); - auth.put("api_key", System.getenv("API_KEY")); + auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search diff --git a/src/test/java/serpapi/GooglePlayTest.java b/src/test/java/serpapi/example/GooglePlayTest.java similarity index 88% rename from src/test/java/serpapi/GooglePlayTest.java rename to src/test/java/serpapi/example/GooglePlayTest.java index 403eab5..b603697 100644 --- a/src/test/java/serpapi/GooglePlayTest.java +++ b/src/test/java/serpapi/example/GooglePlayTest.java @@ -17,12 +17,12 @@ public class GooglePlayTest { @Test public void search() throws SerpApiException { // skip test if no api_key provided - if(System.getenv("API_KEY") == null) + if(System.getenv("SERPAPI_KEY") == null) return; // setup serpapi client Map auth = new HashMap<>(); - auth.put("api_key", System.getenv("API_KEY")); + auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search diff --git a/src/test/java/serpapi/GoogleProductTest.java b/src/test/java/serpapi/example/GoogleProductTest.java similarity index 89% rename from src/test/java/serpapi/GoogleProductTest.java rename to src/test/java/serpapi/example/GoogleProductTest.java index 1ced6d2..65d089f 100644 --- a/src/test/java/serpapi/GoogleProductTest.java +++ b/src/test/java/serpapi/example/GoogleProductTest.java @@ -19,12 +19,12 @@ public class GoogleProductTest { // @Test // public void search() throws SerpApiException { // // skip test if no api_key provided - // if(System.getenv("API_KEY") == null) + // if(System.getenv("SERPAPI_KEY") == null) // return; // // setup serpapi client // Map auth = new HashMap<>(); - // auth.put("api_key", System.getenv("API_KEY")); + // auth.put("api_key", System.getenv("SERPAPI_KEY")); // SerpApi client = new SerpApi(auth); // // run search diff --git a/src/test/java/serpapi/GoogleReverseImageTest.java b/src/test/java/serpapi/example/GoogleReverseImageTest.java similarity index 77% rename from src/test/java/serpapi/GoogleReverseImageTest.java rename to src/test/java/serpapi/example/GoogleReverseImageTest.java index de2abf4..e2f6298 100644 --- a/src/test/java/serpapi/GoogleReverseImageTest.java +++ b/src/test/java/serpapi/example/GoogleReverseImageTest.java @@ -17,12 +17,12 @@ public class GoogleReverseImageTest { @Test public void search() throws SerpApiException { // skip test if no api_key provided - if(System.getenv("API_KEY") == null) + if(System.getenv("SERPAPI_KEY") == null) return; // setup serpapi client Map auth = new HashMap<>(); - auth.put("api_key", System.getenv("API_KEY")); + auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search @@ -30,7 +30,8 @@ public void search() throws SerpApiException { parameter.put("engine", "google_reverse_image"); parameter.put("image_url", "https://i.imgur.com/5bGzZi7.jpg"); JsonObject results = client.search(parameter); - assertTrue(results.getAsJsonArray("image_sizes").size() > 1); + assertTrue(results.has("image_results")); + assertTrue(results.getAsJsonArray("image_results").size() > 0); } } \ No newline at end of file diff --git a/src/test/java/serpapi/GoogleScholarTest.java b/src/test/java/serpapi/example/GoogleScholarTest.java similarity index 88% rename from src/test/java/serpapi/GoogleScholarTest.java rename to src/test/java/serpapi/example/GoogleScholarTest.java index 8ec41a4..7724439 100644 --- a/src/test/java/serpapi/GoogleScholarTest.java +++ b/src/test/java/serpapi/example/GoogleScholarTest.java @@ -17,12 +17,12 @@ public class GoogleScholarTest { @Test public void search() throws SerpApiException { // skip test if no api_key provided - if(System.getenv("API_KEY") == null) + if(System.getenv("SERPAPI_KEY") == null) return; // setup serpapi client Map auth = new HashMap<>(); - auth.put("api_key", System.getenv("API_KEY")); + auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search diff --git a/src/test/java/serpapi/GoogleTest.java b/src/test/java/serpapi/example/GoogleTest.java similarity index 88% rename from src/test/java/serpapi/GoogleTest.java rename to src/test/java/serpapi/example/GoogleTest.java index 0b5acd4..086cdd4 100644 --- a/src/test/java/serpapi/GoogleTest.java +++ b/src/test/java/serpapi/example/GoogleTest.java @@ -17,12 +17,12 @@ public class GoogleTest { @Test public void search() throws SerpApiException { // skip test if no api_key provided - if(System.getenv("API_KEY") == null) + if(System.getenv("SERPAPI_KEY") == null) return; // setup serpapi client Map auth = new HashMap<>(); - auth.put("api_key", System.getenv("API_KEY")); + auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search diff --git a/src/test/java/serpapi/HomeDepotTest.java b/src/test/java/serpapi/example/HomeDepotTest.java similarity index 88% rename from src/test/java/serpapi/HomeDepotTest.java rename to src/test/java/serpapi/example/HomeDepotTest.java index 3a4a345..94f4415 100644 --- a/src/test/java/serpapi/HomeDepotTest.java +++ b/src/test/java/serpapi/example/HomeDepotTest.java @@ -17,12 +17,12 @@ public class HomeDepotTest { @Test public void search() throws SerpApiException { // skip test if no api_key provided - if(System.getenv("API_KEY") == null) + if(System.getenv("SERPAPI_KEY") == null) return; // setup serpapi client Map auth = new HashMap<>(); - auth.put("api_key", System.getenv("API_KEY")); + auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search diff --git a/src/test/java/serpapi/NaverTest.java b/src/test/java/serpapi/example/NaverTest.java similarity index 88% rename from src/test/java/serpapi/NaverTest.java rename to src/test/java/serpapi/example/NaverTest.java index 98b433e..c83a346 100644 --- a/src/test/java/serpapi/NaverTest.java +++ b/src/test/java/serpapi/example/NaverTest.java @@ -17,12 +17,12 @@ public class NaverTest { @Test public void search() throws SerpApiException { // skip test if no api_key provided - if(System.getenv("API_KEY") == null) + if(System.getenv("SERPAPI_KEY") == null) return; // setup serpapi client Map auth = new HashMap<>(); - auth.put("api_key", System.getenv("API_KEY")); + auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search diff --git a/src/test/java/serpapi/WalmartTest.java b/src/test/java/serpapi/example/WalmartTest.java similarity index 88% rename from src/test/java/serpapi/WalmartTest.java rename to src/test/java/serpapi/example/WalmartTest.java index a7d440b..d1b19a9 100644 --- a/src/test/java/serpapi/WalmartTest.java +++ b/src/test/java/serpapi/example/WalmartTest.java @@ -17,12 +17,12 @@ public class WalmartTest { @Test public void search() throws SerpApiException { // skip test if no api_key provided - if(System.getenv("API_KEY") == null) + if(System.getenv("SERPAPI_KEY") == null) return; // setup serpapi client Map auth = new HashMap<>(); - auth.put("api_key", System.getenv("API_KEY")); + auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search diff --git a/src/test/java/serpapi/YahooTest.java b/src/test/java/serpapi/example/YahooTest.java similarity index 88% rename from src/test/java/serpapi/YahooTest.java rename to src/test/java/serpapi/example/YahooTest.java index be147f8..4452465 100644 --- a/src/test/java/serpapi/YahooTest.java +++ b/src/test/java/serpapi/example/YahooTest.java @@ -17,12 +17,12 @@ public class YahooTest { @Test public void search() throws SerpApiException { // skip test if no api_key provided - if(System.getenv("API_KEY") == null) + if(System.getenv("SERPAPI_KEY") == null) return; // setup serpapi client Map auth = new HashMap<>(); - auth.put("api_key", System.getenv("API_KEY")); + auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search diff --git a/src/test/java/serpapi/YoutubeTest.java b/src/test/java/serpapi/example/YoutubeTest.java similarity index 88% rename from src/test/java/serpapi/YoutubeTest.java rename to src/test/java/serpapi/example/YoutubeTest.java index 1d2ce26..4e71a65 100644 --- a/src/test/java/serpapi/YoutubeTest.java +++ b/src/test/java/serpapi/example/YoutubeTest.java @@ -17,12 +17,12 @@ public class YoutubeTest { @Test public void search() throws SerpApiException { // skip test if no api_key provided - if(System.getenv("API_KEY") == null) + if(System.getenv("SERPAPI_KEY") == null) return; // setup serpapi client Map auth = new HashMap<>(); - auth.put("api_key", System.getenv("API_KEY")); + auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search From c610e5056e069ba0b09c4b4954acc23491d74a39 Mon Sep 17 00:00:00 2001 From: Victor Benarbia Date: Sat, 3 Jan 2026 21:54:26 -0600 Subject: [PATCH 02/11] Add JaCoCo coverage support and make coverage target --- Makefile | 5 +++++ build.gradle | 6 ++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 12175ea..8ad9028 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,11 @@ init: test: ./gradlew test --info +# Run test coverage +coverage: + ./gradlew test jacocoTestReport + @echo "Coverage report: build/reports/jacoco/test/html/index.html" + build: clean ./gradlew build publishToMavenLocal -x test @echo "see build/lib" diff --git a/build.gradle b/build.gradle index 7ac1980..c07171f 100644 --- a/build.gradle +++ b/build.gradle @@ -1,10 +1,8 @@ // Java library plugins { id 'java-library' -} - -plugins { - id 'maven-publish' + id 'maven-publish' + id 'jacoco' } // Package default From 3a01d58b32542ee86c3857ae4e0152a7813f5b9f Mon Sep 17 00:00:00 2001 From: Victor Benarbia Date: Sat, 3 Jan 2026 22:26:10 -0600 Subject: [PATCH 03/11] test fail when SERPAPI_KEY is null --- src/test/java/serpapi/AccountApiTest.java | 5 ++++- src/test/java/serpapi/LocationApiTest.java | 8 ++++++-- src/test/java/serpapi/SearchApiTest.java | 7 ++++--- src/test/java/serpapi/SearchArchiveApiTest.java | 8 ++++---- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/test/java/serpapi/AccountApiTest.java b/src/test/java/serpapi/AccountApiTest.java index 8ca2778..364229d 100644 --- a/src/test/java/serpapi/AccountApiTest.java +++ b/src/test/java/serpapi/AccountApiTest.java @@ -12,12 +12,15 @@ import static org.junit.Assert.*; import static org.mockito.Mockito.*; +/*** + * Test SerpApi.account() method. + */ public class AccountApiTest { @Test public void account() throws Exception { if (System.getenv("SERPAPI_KEY") == null) { - return; + fail("SERPAPI_KEY is not set"); } Map parameter = new HashMap(); diff --git a/src/test/java/serpapi/LocationApiTest.java b/src/test/java/serpapi/LocationApiTest.java index 1b0915d..76fe0c3 100644 --- a/src/test/java/serpapi/LocationApiTest.java +++ b/src/test/java/serpapi/LocationApiTest.java @@ -13,12 +13,16 @@ import static org.junit.Assert.*; import static org.mockito.Mockito.*; +/** + * Test SerpApi.location() method. + */ public class LocationApiTest { @Test public void location() throws Exception { - if(System.getenv("SERPAPI_KEY") == null) - return; + if(System.getenv("SERPAPI_KEY") == null) { + fail("SERPAPI_KEY is not set"); + } SerpApi serpapi = new SerpApi(); diff --git a/src/test/java/serpapi/SearchApiTest.java b/src/test/java/serpapi/SearchApiTest.java index 7109619..8f54924 100644 --- a/src/test/java/serpapi/SearchApiTest.java +++ b/src/test/java/serpapi/SearchApiTest.java @@ -10,15 +10,16 @@ import static org.junit.Assert.*; /** - * Test main class + * Test SerpApi.search() method. */ public class SearchApiTest { @Test public void search() throws SerpApiException, InterruptedException { // skip test if no api_key provided - if(System.getenv("SERPAPI_KEY") == null) - return; + if(System.getenv("SERPAPI_KEY") == null) { + fail("SERPAPI_KEY is not set"); + } Map auth = new HashMap<>(); auth.put("api_key", System.getenv("SERPAPI_KEY")); diff --git a/src/test/java/serpapi/SearchArchiveApiTest.java b/src/test/java/serpapi/SearchArchiveApiTest.java index c1e5e99..b8dcf6e 100644 --- a/src/test/java/serpapi/SearchArchiveApiTest.java +++ b/src/test/java/serpapi/SearchArchiveApiTest.java @@ -10,16 +10,16 @@ import static org.junit.Assert.*; /** - * Test main class + * Test SerpApi.searchArchive() method. */ public class SearchArchiveApiTest { - @Test public void searchArchive() throws SerpApiException, InterruptedException { // skip test if no api_key provided - if(System.getenv("SERPAPI_KEY") == null) - return; + if(System.getenv("SERPAPI_KEY") == null) { + fail("SERPAPI_KEY is not set"); + } Map parameter = new HashMap<>(); parameter.put("api_key", System.getenv("SERPAPI_KEY")); From 4788a7be966fa2ad1d1d96c38df6c2b18aa055cb Mon Sep 17 00:00:00 2001 From: Victor Benarbia Date: Sat, 3 Jan 2026 22:38:24 -0600 Subject: [PATCH 04/11] Fix Javadoc warnings in SerpApi, SerpApiHttp, and ParameterStringBuilder --- src/main/java/serpapi/ParameterStringBuilder.java | 6 ++++++ src/main/java/serpapi/SerpApi.java | 2 ++ src/main/java/serpapi/SerpApiHttp.java | 8 ++++++++ 3 files changed, 16 insertions(+) diff --git a/src/main/java/serpapi/ParameterStringBuilder.java b/src/main/java/serpapi/ParameterStringBuilder.java index 231563b..905fb07 100644 --- a/src/main/java/serpapi/ParameterStringBuilder.java +++ b/src/main/java/serpapi/ParameterStringBuilder.java @@ -10,6 +10,12 @@ */ public class ParameterStringBuilder { + /** + * Default constructor + */ + public ParameterStringBuilder() { + } + /*** * getParamsString * @param params search parameters diff --git a/src/main/java/serpapi/SerpApi.java b/src/main/java/serpapi/SerpApi.java index 3a0f425..7a53369 100644 --- a/src/main/java/serpapi/SerpApi.java +++ b/src/main/java/serpapi/SerpApi.java @@ -131,6 +131,8 @@ private JsonObject json(String endpoint, Map parameter) throws S } /*** + * Get the HTTP client used for requests + * * @return http client */ public SerpApiHttp getClient() { diff --git a/src/main/java/serpapi/SerpApiHttp.java b/src/main/java/serpapi/SerpApiHttp.java index 622fd3d..b97605c 100644 --- a/src/main/java/serpapi/SerpApiHttp.java +++ b/src/main/java/serpapi/SerpApiHttp.java @@ -189,6 +189,8 @@ protected void triggerSerpApiException(String content) throws SerpApiException { } /** + * Get the HTTP connection timeout + * * @return current HTTP connection timeout */ public int getHttpConnectionTimeout() { @@ -196,6 +198,8 @@ public int getHttpConnectionTimeout() { } /** + * Set the HTTP connection timeout + * * @param httpConnectionTimeout set HTTP connection timeout */ public void setHttpConnectionTimeout(int httpConnectionTimeout) { @@ -203,6 +207,8 @@ public void setHttpConnectionTimeout(int httpConnectionTimeout) { } /** + * Get the HTTP read timeout + * * @return current HTTP read timeout */ public int getHttpReadTimeout() { @@ -210,6 +216,8 @@ public int getHttpReadTimeout() { } /** + * Set the HTTP read timeout + * * @param httpReadTimeout set HTTP read timeout */ public void setHttpReadTimeout(int httpReadTimeout) { From 334e07c1815bcb8fb8288d7b0e6e98f3f5461859 Mon Sep 17 00:00:00 2001 From: Victor Benarbia Date: Sat, 3 Jan 2026 22:39:23 -0600 Subject: [PATCH 05/11] Enhance Makefile with additional build targets and update Javadoc command to use Gradle wrapper --- Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 8ad9028..50db6ae 100644 --- a/Makefile +++ b/Makefile @@ -20,10 +20,12 @@ coverage: ./gradlew test jacocoTestReport @echo "Coverage report: build/reports/jacoco/test/html/index.html" +# Build the project build: clean ./gradlew build publishToMavenLocal -x test @echo "see build/lib" +# Build the demo project oobt: build $(MAKE) -C demo all @@ -31,8 +33,9 @@ oobt: build readme: erb -T '-' README.md.erb > README.md +# Build the javadoc doc: - gradle javadoc --info --warning-mode all + ./gradlew javadoc --info --warning-mode all # Create a release using GitHub release: doc build From ade443a28503dbc35c7eedbe76d05502b505846d Mon Sep 17 00:00:00 2001 From: Ryan Schafer Date: Wed, 21 Feb 2024 15:10:09 -0800 Subject: [PATCH 06/11] Clarify usage instructions in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 22a91cc..4ccadab 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ We provided a fully working example. ```bash git clone https://github.com/serpapi/serpapi-java.git cd serpapi-java/demo -make run api_key= +make all API_KEY= ``` Note: You need an account with SerpApi to obtain this key from: https://serpapi.com/dashboard From 85cef8923bdab3d11958de38a09d6630e8ca2b28 Mon Sep 17 00:00:00 2001 From: Victor Benarbia Date: Sat, 3 Jan 2026 23:03:34 -0600 Subject: [PATCH 07/11] Update README and example tests to reflect new package structure and version changes --- README.md | 122 +++++++++--------- README.md.erb | 51 ++++---- .../serpapi/example/AppleAppStoreTest.java | 3 +- src/test/java/serpapi/example/BaiduTest.java | 3 +- src/test/java/serpapi/example/BingTest.java | 3 +- .../java/serpapi/example/DuckduckgoTest.java | 3 +- src/test/java/serpapi/example/EbayTest.java | 3 +- .../example/GoogleAutocompleteTest.java | 3 +- .../serpapi/example/GoogleEventsTest.java | 3 +- .../serpapi/example/GoogleImagesTest.java | 3 +- .../java/serpapi/example/GoogleJobsTest.java | 3 +- .../example/GoogleLocalServicesTest.java | 37 ------ .../java/serpapi/example/GoogleMapsTest.java | 3 +- .../java/serpapi/example/GooglePlayTest.java | 3 +- .../serpapi/example/GoogleProductTest.java | 3 +- .../example/GoogleReverseImageTest.java | 3 +- .../serpapi/example/GoogleScholarTest.java | 3 +- src/test/java/serpapi/example/GoogleTest.java | 3 +- .../java/serpapi/example/HomeDepotTest.java | 3 +- src/test/java/serpapi/example/NaverTest.java | 3 +- .../java/serpapi/example/WalmartTest.java | 3 +- src/test/java/serpapi/example/YahooTest.java | 3 +- .../java/serpapi/example/YoutubeTest.java | 3 +- 23 files changed, 127 insertions(+), 143 deletions(-) delete mode 100644 src/test/java/serpapi/example/GoogleLocalServicesTest.java diff --git a/README.md b/README.md index 4ccadab..0ff4e73 100644 --- a/README.md +++ b/README.md @@ -21,14 +21,14 @@ repositories { } dependencies { - implementation 'com.github.serpapi:serpapi-java:1.0.0' + implementation 'com.github.serpapi:serpapi-java:1.1.0' } ``` To list all the version available. https://jitpack.io/api/builds/com.github.serpapi/serpapi-java -or you can download the jar file from https://github.com/serpapi/serpapi-java.git +or you can download the jar file from https://github.com/serpapi/serpapi-java/releases Note: jitpack.io enables to download maven package directly from github release. @@ -169,8 +169,9 @@ it prints your account information. ### Search bing ```java +// setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); +auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search @@ -181,13 +182,14 @@ JsonObject results = client.search(parameter); System.out.println(results.toString()); ``` - * source code: [src/test/java/serpapi/BingTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/BingTest.java) + * source code: [src/test/java/serpapi/example/BingTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/BingTest.java) see: [https://serpapi.com/bing-search-api](https://serpapi.com/bing-search-api) ### Search baidu ```java +// setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); +auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search @@ -198,13 +200,14 @@ JsonObject results = client.search(parameter); System.out.println(results.toString()); ``` - * source code: [src/test/java/serpapi/BaiduTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/BaiduTest.java) + * source code: [src/test/java/serpapi/example/BaiduTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/BaiduTest.java) see: [https://serpapi.com/baidu-search-api](https://serpapi.com/baidu-search-api) ### Search yahoo ```java +// setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); +auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search @@ -215,13 +218,14 @@ JsonObject results = client.search(parameter); System.out.println(results.toString()); ``` - * source code: [src/test/java/serpapi/YahooTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/YahooTest.java) + * source code: [src/test/java/serpapi/example/YahooTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/YahooTest.java) see: [https://serpapi.com/yahoo-search-api](https://serpapi.com/yahoo-search-api) ### Search youtube ```java +// setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); +auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search @@ -232,13 +236,14 @@ JsonObject results = client.search(parameter); System.out.println(results.toString()); ``` - * source code: [src/test/java/serpapi/YoutubeTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/YoutubeTest.java) + * source code: [src/test/java/serpapi/example/YoutubeTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/YoutubeTest.java) see: [https://serpapi.com/youtube-search-api](https://serpapi.com/youtube-search-api) ### Search walmart ```java +// setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); +auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search @@ -249,13 +254,14 @@ JsonObject results = client.search(parameter); System.out.println(results.toString()); ``` - * source code: [src/test/java/serpapi/WalmartTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/WalmartTest.java) + * source code: [src/test/java/serpapi/example/WalmartTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/WalmartTest.java) see: [https://serpapi.com/walmart-search-api](https://serpapi.com/walmart-search-api) ### Search ebay ```java +// setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); +auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search @@ -266,13 +272,14 @@ JsonObject results = client.search(parameter); System.out.println(results.toString()); ``` - * source code: [src/test/java/serpapi/EbayTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/EbayTest.java) + * source code: [src/test/java/serpapi/example/EbayTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/EbayTest.java) see: [https://serpapi.com/ebay-search-api](https://serpapi.com/ebay-search-api) ### Search naver ```java +// setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); +auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search @@ -283,13 +290,14 @@ JsonObject results = client.search(parameter); System.out.println(results.toString()); ``` - * source code: [src/test/java/serpapi/NaverTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/NaverTest.java) + * source code: [src/test/java/serpapi/example/NaverTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/NaverTest.java) see: [https://serpapi.com/naver-search-api](https://serpapi.com/naver-search-api) ### Search home depot ```java +// setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); +auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search @@ -300,13 +308,14 @@ JsonObject results = client.search(parameter); System.out.println(results.toString()); ``` - * source code: [src/test/java/serpapi/HomeDepotTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/HomeDepotTest.java) + * source code: [src/test/java/serpapi/example/HomeDepotTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/HomeDepotTest.java) see: [https://serpapi.com/home-depot-search-api](https://serpapi.com/home-depot-search-api) ### Search apple app store ```java +// setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); +auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search @@ -317,13 +326,14 @@ JsonObject results = client.search(parameter); System.out.println(results.toString()); ``` - * source code: [src/test/java/serpapi/AppleAppStoreTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/AppleAppStoreTest.java) + * source code: [src/test/java/serpapi/example/AppleAppStoreTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/AppleAppStoreTest.java) see: [https://serpapi.com/apple-app-store](https://serpapi.com/apple-app-store) ### Search duckduckgo ```java +// setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); +auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search @@ -334,13 +344,14 @@ JsonObject results = client.search(parameter); System.out.println(results.toString()); ``` - * source code: [src/test/java/serpapi/DuckduckgoTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/DuckduckgoTest.java) + * source code: [src/test/java/serpapi/example/DuckduckgoTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/DuckduckgoTest.java) see: [https://serpapi.com/duckduckgo-search-api](https://serpapi.com/duckduckgo-search-api) ### Search google ```java +// setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); +auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search @@ -352,13 +363,14 @@ JsonObject results = client.search(parameter); System.out.println(results.toString()); ``` - * source code: [src/test/java/serpapi/GoogleTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/GoogleTest.java) + * source code: [src/test/java/serpapi/example/GoogleTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/GoogleTest.java) see: [https://serpapi.com/search-api](https://serpapi.com/search-api) ### Search google scholar ```java +// setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); +auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search @@ -369,13 +381,14 @@ JsonObject results = client.search(parameter); System.out.println(results.toString()); ``` - * source code: [src/test/java/serpapi/GoogleScholarTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/GoogleScholarTest.java) + * source code: [src/test/java/serpapi/example/GoogleScholarTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/GoogleScholarTest.java) see: [https://serpapi.com/google-scholar-api](https://serpapi.com/google-scholar-api) ### Search google autocomplete ```java +// setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); +auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search @@ -386,15 +399,16 @@ JsonObject results = client.search(parameter); System.out.println(results.toString()); ``` - * source code: [src/test/java/serpapi/GoogleAutocompleteTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/GoogleAutocompleteTest.java) + * source code: [src/test/java/serpapi/example/GoogleAutocompleteTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/GoogleAutocompleteTest.java) see: [https://serpapi.com/google-autocomplete-api](https://serpapi.com/google-autocomplete-api) ### Search google product ```java + // return; // // setup serpapi client // Map auth = new HashMap<>(); - // auth.put("api_key", "your_api_key"); + // auth.put("api_key", System.getenv("SERPAPI_KEY")); // SerpApi client = new SerpApi(auth); // // run search @@ -406,13 +420,14 @@ see: [https://serpapi.com/google-autocomplete-api](https://serpapi.com/google-au System.out.println(results.toString()); ``` - * source code: [src/test/java/serpapi/GoogleProductTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/GoogleProductTest.java) + * source code: [src/test/java/serpapi/example/GoogleProductTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/GoogleProductTest.java) see: [https://serpapi.com/google-product-api](https://serpapi.com/google-product-api) ### Search google reverse image ```java +// setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); +auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search @@ -423,13 +438,14 @@ JsonObject results = client.search(parameter); System.out.println(results.toString()); ``` - * source code: [src/test/java/serpapi/GoogleReverseImageTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/GoogleReverseImageTest.java) + * source code: [src/test/java/serpapi/example/GoogleReverseImageTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/GoogleReverseImageTest.java) see: [https://serpapi.com/google-reverse-image](https://serpapi.com/google-reverse-image) ### Search google events ```java +// setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); +auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search @@ -440,31 +456,14 @@ JsonObject results = client.search(parameter); System.out.println(results.toString()); ``` - * source code: [src/test/java/serpapi/GoogleEventsTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/GoogleEventsTest.java) + * source code: [src/test/java/serpapi/example/GoogleEventsTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/GoogleEventsTest.java) see: [https://serpapi.com/google-events-api](https://serpapi.com/google-events-api) -### Search google local services -```java -Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); -SerpApi client = new SerpApi(auth); - -// run search -Map parameter = new HashMap<>(); -parameter.put("engine", "google_local_services"); -parameter.put("q", "electrician"); -parameter.put("data_cid", "6745062158417646970"); -JsonObject results = client.search(parameter); -System.out.println(results.toString()); -``` - - * source code: [src/test/java/serpapi/GoogleLocalServicesTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/GoogleLocalServicesTest.java) -see: [https://serpapi.com/google-local-services-api](https://serpapi.com/google-local-services-api) - ### Search google maps ```java +// setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); +auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search @@ -477,13 +476,14 @@ JsonObject results = client.search(parameter); System.out.println(results.toString()); ``` - * source code: [src/test/java/serpapi/GoogleMapsTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/GoogleMapsTest.java) + * source code: [src/test/java/serpapi/example/GoogleMapsTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/GoogleMapsTest.java) see: [https://serpapi.com/google-maps-api](https://serpapi.com/google-maps-api) ### Search google jobs ```java +// setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); +auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search @@ -494,13 +494,14 @@ JsonObject results = client.search(parameter); System.out.println(results.toString()); ``` - * source code: [src/test/java/serpapi/GoogleJobsTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/GoogleJobsTest.java) + * source code: [src/test/java/serpapi/example/GoogleJobsTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/GoogleJobsTest.java) see: [https://serpapi.com/google-jobs-api](https://serpapi.com/google-jobs-api) ### Search google play ```java +// setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); +auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search @@ -512,13 +513,14 @@ JsonObject results = client.search(parameter); System.out.println(results.toString()); ``` - * source code: [src/test/java/serpapi/GooglePlayTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/GooglePlayTest.java) + * source code: [src/test/java/serpapi/example/GooglePlayTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/GooglePlayTest.java) see: [https://serpapi.com/google-play-api](https://serpapi.com/google-play-api) ### Search google images ```java +// setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); +auth.put("api_key", System.getenv("SERPAPI_KEY")); SerpApi client = new SerpApi(auth); // run search @@ -531,7 +533,7 @@ JsonObject results = client.search(parameter); System.out.println(results.toString()); ``` - * source code: [src/test/java/serpapi/GoogleImagesTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/GoogleImagesTest.java) + * source code: [src/test/java/serpapi/example/GoogleImagesTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/GoogleImagesTest.java) see: [https://serpapi.com/images-results](https://serpapi.com/images-results) diff --git a/README.md.erb b/README.md.erb index ffea8d7..915e765 100644 --- a/README.md.erb +++ b/README.md.erb @@ -2,6 +2,9 @@ def snippet(format, path) lines = File.new(path).readlines stop = lines.find_index { |line| line =~ /assertTrue/} +if stop.nil? + raise "No assertTrue found in #{path}" +end slice = File.new(path).readlines[23..stop-1] slice << "System.out.println(results.toString());" buf = slice.map { |l| l.gsub(/(^\s\s\s\s)/, '')}.join @@ -33,14 +36,14 @@ repositories { } dependencies { - implementation 'com.github.serpapi:serpapi-java:1.0.0' + implementation 'com.github.serpapi:serpapi-java:1.1.0' } ``` To list all the version available. https://jitpack.io/api/builds/com.github.serpapi/serpapi-java -or you can download the jar file from https://github.com/serpapi/serpapi-java.git +or you can download the jar file from https://github.com/serpapi/serpapi-java/releases Note: jitpack.io enables to download maven package directly from github release. @@ -180,87 +183,83 @@ it prints your account information. ## Examples in java ### Search bing -<%= snippet('java', 'src/test/java/serpapi/BingTest.java') %> +<%= snippet('java', 'src/test/java/serpapi/example/BingTest.java') %> see: [https://serpapi.com/bing-search-api](https://serpapi.com/bing-search-api) ### Search baidu -<%= snippet('java', 'src/test/java/serpapi/BaiduTest.java') %> +<%= snippet('java', 'src/test/java/serpapi/example/BaiduTest.java') %> see: [https://serpapi.com/baidu-search-api](https://serpapi.com/baidu-search-api) ### Search yahoo -<%= snippet('java', 'src/test/java/serpapi/YahooTest.java') %> +<%= snippet('java', 'src/test/java/serpapi/example/YahooTest.java') %> see: [https://serpapi.com/yahoo-search-api](https://serpapi.com/yahoo-search-api) ### Search youtube -<%= snippet('java', 'src/test/java/serpapi/YoutubeTest.java') %> +<%= snippet('java', 'src/test/java/serpapi/example/YoutubeTest.java') %> see: [https://serpapi.com/youtube-search-api](https://serpapi.com/youtube-search-api) ### Search walmart -<%= snippet('java', 'src/test/java/serpapi/WalmartTest.java') %> +<%= snippet('java', 'src/test/java/serpapi/example/WalmartTest.java') %> see: [https://serpapi.com/walmart-search-api](https://serpapi.com/walmart-search-api) ### Search ebay -<%= snippet('java', 'src/test/java/serpapi/EbayTest.java') %> +<%= snippet('java', 'src/test/java/serpapi/example/EbayTest.java') %> see: [https://serpapi.com/ebay-search-api](https://serpapi.com/ebay-search-api) ### Search naver -<%= snippet('java', 'src/test/java/serpapi/NaverTest.java') %> +<%= snippet('java', 'src/test/java/serpapi/example/NaverTest.java') %> see: [https://serpapi.com/naver-search-api](https://serpapi.com/naver-search-api) ### Search home depot -<%= snippet('java', 'src/test/java/serpapi/HomeDepotTest.java') %> +<%= snippet('java', 'src/test/java/serpapi/example/HomeDepotTest.java') %> see: [https://serpapi.com/home-depot-search-api](https://serpapi.com/home-depot-search-api) ### Search apple app store -<%= snippet('java', 'src/test/java/serpapi/AppleAppStoreTest.java') %> +<%= snippet('java', 'src/test/java/serpapi/example/AppleAppStoreTest.java') %> see: [https://serpapi.com/apple-app-store](https://serpapi.com/apple-app-store) ### Search duckduckgo -<%= snippet('java', 'src/test/java/serpapi/DuckduckgoTest.java') %> +<%= snippet('java', 'src/test/java/serpapi/example/DuckduckgoTest.java') %> see: [https://serpapi.com/duckduckgo-search-api](https://serpapi.com/duckduckgo-search-api) ### Search google -<%= snippet('java', 'src/test/java/serpapi/GoogleTest.java') %> +<%= snippet('java', 'src/test/java/serpapi/example/GoogleTest.java') %> see: [https://serpapi.com/search-api](https://serpapi.com/search-api) ### Search google scholar -<%= snippet('java', 'src/test/java/serpapi/GoogleScholarTest.java') %> +<%= snippet('java', 'src/test/java/serpapi/example/GoogleScholarTest.java') %> see: [https://serpapi.com/google-scholar-api](https://serpapi.com/google-scholar-api) ### Search google autocomplete -<%= snippet('java', 'src/test/java/serpapi/GoogleAutocompleteTest.java') %> +<%= snippet('java', 'src/test/java/serpapi/example/GoogleAutocompleteTest.java') %> see: [https://serpapi.com/google-autocomplete-api](https://serpapi.com/google-autocomplete-api) ### Search google product -<%= snippet('java', 'src/test/java/serpapi/GoogleProductTest.java') %> +<%= snippet('java', 'src/test/java/serpapi/example/GoogleProductTest.java') %> see: [https://serpapi.com/google-product-api](https://serpapi.com/google-product-api) ### Search google reverse image -<%= snippet('java', 'src/test/java/serpapi/GoogleReverseImageTest.java') %> +<%= snippet('java', 'src/test/java/serpapi/example/GoogleReverseImageTest.java') %> see: [https://serpapi.com/google-reverse-image](https://serpapi.com/google-reverse-image) ### Search google events -<%= snippet('java', 'src/test/java/serpapi/GoogleEventsTest.java') %> +<%= snippet('java', 'src/test/java/serpapi/example/GoogleEventsTest.java') %> see: [https://serpapi.com/google-events-api](https://serpapi.com/google-events-api) -### Search google local services -<%= snippet('java', 'src/test/java/serpapi/GoogleLocalServicesTest.java') %> -see: [https://serpapi.com/google-local-services-api](https://serpapi.com/google-local-services-api) - ### Search google maps -<%= snippet('java', 'src/test/java/serpapi/GoogleMapsTest.java') %> +<%= snippet('java', 'src/test/java/serpapi/example/GoogleMapsTest.java') %> see: [https://serpapi.com/google-maps-api](https://serpapi.com/google-maps-api) ### Search google jobs -<%= snippet('java', 'src/test/java/serpapi/GoogleJobsTest.java') %> +<%= snippet('java', 'src/test/java/serpapi/example/GoogleJobsTest.java') %> see: [https://serpapi.com/google-jobs-api](https://serpapi.com/google-jobs-api) ### Search google play -<%= snippet('java', 'src/test/java/serpapi/GooglePlayTest.java') %> +<%= snippet('java', 'src/test/java/serpapi/example/GooglePlayTest.java') %> see: [https://serpapi.com/google-play-api](https://serpapi.com/google-play-api) ### Search google images -<%= snippet('java', 'src/test/java/serpapi/GoogleImagesTest.java') %> +<%= snippet('java', 'src/test/java/serpapi/example/GoogleImagesTest.java') %> see: [https://serpapi.com/images-results](https://serpapi.com/images-results) diff --git a/src/test/java/serpapi/example/AppleAppStoreTest.java b/src/test/java/serpapi/example/AppleAppStoreTest.java index a1af4f5..c00d6ee 100644 --- a/src/test/java/serpapi/example/AppleAppStoreTest.java +++ b/src/test/java/serpapi/example/AppleAppStoreTest.java @@ -1,4 +1,5 @@ -package serpapi; +package serpapi.example; +import serpapi.*; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; diff --git a/src/test/java/serpapi/example/BaiduTest.java b/src/test/java/serpapi/example/BaiduTest.java index cea68d7..650301c 100644 --- a/src/test/java/serpapi/example/BaiduTest.java +++ b/src/test/java/serpapi/example/BaiduTest.java @@ -1,4 +1,5 @@ -package serpapi; +package serpapi.example; +import serpapi.*; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; diff --git a/src/test/java/serpapi/example/BingTest.java b/src/test/java/serpapi/example/BingTest.java index 6adacf7..b8532bf 100644 --- a/src/test/java/serpapi/example/BingTest.java +++ b/src/test/java/serpapi/example/BingTest.java @@ -1,4 +1,5 @@ -package serpapi; +package serpapi.example; +import serpapi.*; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; diff --git a/src/test/java/serpapi/example/DuckduckgoTest.java b/src/test/java/serpapi/example/DuckduckgoTest.java index 5a5ba47..80d2788 100644 --- a/src/test/java/serpapi/example/DuckduckgoTest.java +++ b/src/test/java/serpapi/example/DuckduckgoTest.java @@ -1,4 +1,5 @@ -package serpapi; +package serpapi.example; +import serpapi.*; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; diff --git a/src/test/java/serpapi/example/EbayTest.java b/src/test/java/serpapi/example/EbayTest.java index 874f48e..c5019e8 100644 --- a/src/test/java/serpapi/example/EbayTest.java +++ b/src/test/java/serpapi/example/EbayTest.java @@ -1,4 +1,5 @@ -package serpapi; +package serpapi.example; +import serpapi.*; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; diff --git a/src/test/java/serpapi/example/GoogleAutocompleteTest.java b/src/test/java/serpapi/example/GoogleAutocompleteTest.java index a279363..ebbad6a 100644 --- a/src/test/java/serpapi/example/GoogleAutocompleteTest.java +++ b/src/test/java/serpapi/example/GoogleAutocompleteTest.java @@ -1,4 +1,5 @@ -package serpapi; +package serpapi.example; +import serpapi.*; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; diff --git a/src/test/java/serpapi/example/GoogleEventsTest.java b/src/test/java/serpapi/example/GoogleEventsTest.java index df46c1a..e6caf46 100644 --- a/src/test/java/serpapi/example/GoogleEventsTest.java +++ b/src/test/java/serpapi/example/GoogleEventsTest.java @@ -1,4 +1,5 @@ -package serpapi; +package serpapi.example; +import serpapi.*; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; diff --git a/src/test/java/serpapi/example/GoogleImagesTest.java b/src/test/java/serpapi/example/GoogleImagesTest.java index cf27d53..03b338e 100644 --- a/src/test/java/serpapi/example/GoogleImagesTest.java +++ b/src/test/java/serpapi/example/GoogleImagesTest.java @@ -1,4 +1,5 @@ -package serpapi; +package serpapi.example; +import serpapi.*; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; diff --git a/src/test/java/serpapi/example/GoogleJobsTest.java b/src/test/java/serpapi/example/GoogleJobsTest.java index eb274c2..c44c2f7 100644 --- a/src/test/java/serpapi/example/GoogleJobsTest.java +++ b/src/test/java/serpapi/example/GoogleJobsTest.java @@ -1,4 +1,5 @@ -package serpapi; +package serpapi.example; +import serpapi.*; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; diff --git a/src/test/java/serpapi/example/GoogleLocalServicesTest.java b/src/test/java/serpapi/example/GoogleLocalServicesTest.java deleted file mode 100644 index b3574d4..0000000 --- a/src/test/java/serpapi/example/GoogleLocalServicesTest.java +++ /dev/null @@ -1,37 +0,0 @@ -package serpapi; - -import com.google.gson.JsonObject; -import com.google.gson.JsonPrimitive; -import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; - -import static org.junit.Assert.*; - -/** - * Test main class - */ -public class GoogleLocalServicesTest { - - @Test - public void search() throws SerpApiException { - // skip test if no api_key provided - if(System.getenv("SERPAPI_KEY") == null) - return; - - // setup serpapi client - Map auth = new HashMap<>(); - auth.put("api_key", System.getenv("SERPAPI_KEY")); - SerpApi client = new SerpApi(auth); - - // run search - Map parameter = new HashMap<>(); - parameter.put("engine", "google_local_services"); - parameter.put("q", "electrician"); - parameter.put("data_cid", "6745062158417646970"); - JsonObject results = client.search(parameter); - assertTrue(results.getAsJsonArray("local_ads").size() > 5); - } - -} \ No newline at end of file diff --git a/src/test/java/serpapi/example/GoogleMapsTest.java b/src/test/java/serpapi/example/GoogleMapsTest.java index 37ea934..ab1c45d 100644 --- a/src/test/java/serpapi/example/GoogleMapsTest.java +++ b/src/test/java/serpapi/example/GoogleMapsTest.java @@ -1,4 +1,5 @@ -package serpapi; +package serpapi.example; +import serpapi.*; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; diff --git a/src/test/java/serpapi/example/GooglePlayTest.java b/src/test/java/serpapi/example/GooglePlayTest.java index b603697..488ea27 100644 --- a/src/test/java/serpapi/example/GooglePlayTest.java +++ b/src/test/java/serpapi/example/GooglePlayTest.java @@ -1,4 +1,5 @@ -package serpapi; +package serpapi.example; +import serpapi.*; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; diff --git a/src/test/java/serpapi/example/GoogleProductTest.java b/src/test/java/serpapi/example/GoogleProductTest.java index 65d089f..1992b8c 100644 --- a/src/test/java/serpapi/example/GoogleProductTest.java +++ b/src/test/java/serpapi/example/GoogleProductTest.java @@ -1,4 +1,5 @@ -package serpapi; +package serpapi.example; +import serpapi.*; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; diff --git a/src/test/java/serpapi/example/GoogleReverseImageTest.java b/src/test/java/serpapi/example/GoogleReverseImageTest.java index e2f6298..c8830e0 100644 --- a/src/test/java/serpapi/example/GoogleReverseImageTest.java +++ b/src/test/java/serpapi/example/GoogleReverseImageTest.java @@ -1,4 +1,5 @@ -package serpapi; +package serpapi.example; +import serpapi.*; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; diff --git a/src/test/java/serpapi/example/GoogleScholarTest.java b/src/test/java/serpapi/example/GoogleScholarTest.java index 7724439..244c2ba 100644 --- a/src/test/java/serpapi/example/GoogleScholarTest.java +++ b/src/test/java/serpapi/example/GoogleScholarTest.java @@ -1,4 +1,5 @@ -package serpapi; +package serpapi.example; +import serpapi.*; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; diff --git a/src/test/java/serpapi/example/GoogleTest.java b/src/test/java/serpapi/example/GoogleTest.java index 086cdd4..08d050d 100644 --- a/src/test/java/serpapi/example/GoogleTest.java +++ b/src/test/java/serpapi/example/GoogleTest.java @@ -1,4 +1,5 @@ -package serpapi; +package serpapi.example; +import serpapi.*; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; diff --git a/src/test/java/serpapi/example/HomeDepotTest.java b/src/test/java/serpapi/example/HomeDepotTest.java index 94f4415..4e0d1bb 100644 --- a/src/test/java/serpapi/example/HomeDepotTest.java +++ b/src/test/java/serpapi/example/HomeDepotTest.java @@ -1,4 +1,5 @@ -package serpapi; +package serpapi.example; +import serpapi.*; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; diff --git a/src/test/java/serpapi/example/NaverTest.java b/src/test/java/serpapi/example/NaverTest.java index c83a346..850fb6e 100644 --- a/src/test/java/serpapi/example/NaverTest.java +++ b/src/test/java/serpapi/example/NaverTest.java @@ -1,4 +1,5 @@ -package serpapi; +package serpapi.example; +import serpapi.*; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; diff --git a/src/test/java/serpapi/example/WalmartTest.java b/src/test/java/serpapi/example/WalmartTest.java index d1b19a9..ef21efa 100644 --- a/src/test/java/serpapi/example/WalmartTest.java +++ b/src/test/java/serpapi/example/WalmartTest.java @@ -1,4 +1,5 @@ -package serpapi; +package serpapi.example; +import serpapi.*; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; diff --git a/src/test/java/serpapi/example/YahooTest.java b/src/test/java/serpapi/example/YahooTest.java index 4452465..2ea9a29 100644 --- a/src/test/java/serpapi/example/YahooTest.java +++ b/src/test/java/serpapi/example/YahooTest.java @@ -1,4 +1,5 @@ -package serpapi; +package serpapi.example; +import serpapi.*; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; diff --git a/src/test/java/serpapi/example/YoutubeTest.java b/src/test/java/serpapi/example/YoutubeTest.java index 4e71a65..ebadcc9 100644 --- a/src/test/java/serpapi/example/YoutubeTest.java +++ b/src/test/java/serpapi/example/YoutubeTest.java @@ -1,4 +1,5 @@ -package serpapi; +package serpapi.example; +import serpapi.*; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; From cc7c80f1cefc02000e3963bbed430fa5196a2758 Mon Sep 17 00:00:00 2001 From: Victor Benarbia Date: Sun, 4 Jan 2026 00:03:01 -0600 Subject: [PATCH 08/11] Enhance build configuration and refactor SerpApiHttp for improved HTTP handling - Updated JaCoCo configuration in build.gradle for better test coverage reporting. - Refactored SerpApiHttp to utilize HttpClient for HTTP requests, improving performance and readability. - Adjusted Makefile and demo Makefile to use the Gradle wrapper consistently. - Added a new test class for Google Local Services to validate API functionality. - Updated existing tests to ensure they handle null API keys gracefully. --- Makefile | 8 +- build.gradle | 36 +++- demo/Makefile | 4 +- src/main/java/serpapi/SerpApiHttp.java | 154 +++++------------- .../example/GoogleLocalServicesTest.java | 39 +++++ .../example/GoogleReverseImageTest.java | 3 +- 6 files changed, 114 insertions(+), 130 deletions(-) create mode 100644 src/test/java/serpapi/example/GoogleLocalServicesTest.java diff --git a/Makefile b/Makefile index 50db6ae..e8602bd 100644 --- a/Makefile +++ b/Makefile @@ -8,12 +8,12 @@ clean: # Initialize gradle wrapper init: - gradle wrapper + ./gradlew wrapper chmod +x ./gradlew # Run gradle test with information test: - ./gradlew test --info + ./gradlew test # Run test coverage coverage: @@ -23,7 +23,7 @@ coverage: # Build the project build: clean ./gradlew build publishToMavenLocal -x test - @echo "see build/lib" + @echo "see build/libs" # Build the demo project oobt: build @@ -35,7 +35,7 @@ readme: # Build the javadoc doc: - ./gradlew javadoc --info --warning-mode all + ./gradlew javadoc --warning-mode all # Create a release using GitHub release: doc build diff --git a/build.gradle b/build.gradle index c07171f..9db7e71 100644 --- a/build.gradle +++ b/build.gradle @@ -5,14 +5,29 @@ plugins { id 'jacoco' } +jacoco { + toolVersion = "0.8.12" +} + +jacocoTestReport { + reports { + xml.required = true + html.required = true + } +} + // Package default -archivesBaseName = 'serpapi' +base { + archivesName = 'serpapi' +} version = '1.1.0' group = 'com.github.serpapi' -// java version -sourceCompatibility = 21 -targetCompatibility = 21 +java { + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 + withJavadocJar() +} // Load repositories repositories { @@ -21,10 +36,6 @@ repositories { maven { url "https://jitpack.io" } } -java { - withJavadocJar() -} - dependencies { implementation 'com.google.code.gson:gson:2.9.0' @@ -45,6 +56,15 @@ tasks.named('jar') { } } +test { + testLogging { + events "passed", "skipped", "failed" + exceptionFormat "short" + showStackTraces true + showStandardStreams true + } +} + publishing { publications { mavenJava(MavenPublication) { diff --git a/demo/Makefile b/demo/Makefile index a98d3b8..5a34fd2 100644 --- a/demo/Makefile +++ b/demo/Makefile @@ -9,7 +9,7 @@ endif all: init clean build run init: - gradle wrapper + ../gradlew wrapper chmod +x ./gradlew clean: @@ -26,4 +26,4 @@ build: clean @./gradlew build run: - @./gradlew run --args="$(API_KEY)" + @./gradlew run --args="$(SERPAPI_KEY)" diff --git a/src/main/java/serpapi/SerpApiHttp.java b/src/main/java/serpapi/SerpApiHttp.java index b97605c..33129e9 100644 --- a/src/main/java/serpapi/SerpApiHttp.java +++ b/src/main/java/serpapi/SerpApiHttp.java @@ -1,25 +1,23 @@ package serpapi; -import javax.net.ssl.*; import java.io.*; -import java.net.HttpURLConnection; -import java.net.URL; -import java.security.KeyManagementException; -import java.security.NoSuchAlgorithmException; -import java.security.cert.X509Certificate; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; import java.util.Map; import com.google.gson.Gson; import com.google.gson.JsonObject; -import com.google.gson.JsonPrimitive; /** * HTTPS client for Serp API */ public class SerpApiHttp { // http request configuration - private int httpConnectionTimeout; - private int httpReadTimeout; + private int httpConnectionTimeout = 60000; + private int httpReadTimeout = 60000; /** * current API version @@ -41,84 +39,20 @@ public class SerpApiHttp { */ public String path; + /** + * HTTP client + */ + private HttpClient httpClient; + /*** * Constructor * @param path HTTP url path */ public SerpApiHttp(String path) { this.path = path; - } - - /*** - * Connect socket connection - * - * @param path url end point - * @param parameter client parameters like: { "q": "coffee", "location": "Austin, TX"} - * @return HttpURLConnection connection object - * @throws SerpApiException wraps error message - */ - protected HttpURLConnection connect(String path, Map parameter) throws SerpApiException { - HttpURLConnection con; - try { - allowHTTPS(); - String query = ParameterStringBuilder.getParamsString(parameter); - URL url = new URL(BACKEND + path + "?" + query); - con = (HttpURLConnection) url.openConnection(); - con.setRequestMethod("GET"); - } catch (IOException e) { - throw new SerpApiException(e); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - throw new SerpApiException(e); - } catch (KeyManagementException e) { - e.printStackTrace(); - throw new SerpApiException(e); - } - - String outputFormat = parameter.get("output"); - if (outputFormat == null) { - throw new SerpApiException("output format must be defined: " + path); - } else if (outputFormat.startsWith("json")) { - con.setRequestProperty("Content-Type", "application/json"); - } - con.setConnectTimeout(getHttpConnectionTimeout()); - con.setReadTimeout(getHttpReadTimeout()); - - con.setDoOutput(true); - return con; - } - - // Allow HTTPS support with legacy java version - private void allowHTTPS() throws NoSuchAlgorithmException, KeyManagementException { - TrustManager[] trustAllCerts; - trustAllCerts = new TrustManager[] { new X509TrustManager() { - public X509Certificate[] getAcceptedIssuers() { - return null; - } - - public void checkClientTrusted(X509Certificate[] certs, String authType) { - } - - public void checkServerTrusted(X509Certificate[] certs, String authType) { - } - - } }; - - SSLContext sc = SSLContext.getInstance("SSL"); - sc.init(null, trustAllCerts, new java.security.SecureRandom()); - HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); - - // Create all-trusting host name verifier - HostnameVerifier allHostsValid = new HostnameVerifier() { - public boolean verify(String hostname, SSLSession session) { - return true; - } - }; - // Install the all-trusting host verifier - HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid); - /* - * end of the fix - */ + this.httpClient = HttpClient.newBuilder() + .connectTimeout(Duration.ofMillis(httpConnectionTimeout)) + .build(); } /*** @@ -129,47 +63,35 @@ public boolean verify(String hostname, SSLSession session) { * @throws SerpApiException wraps error message */ public String get(Map parameter) throws SerpApiException { - HttpURLConnection con = connect(this.path, parameter); - - // Get HTTP status - int statusCode = -1; - // Hold response stream - InputStream is = null; - // Read buffer - BufferedReader in = null; + String query; try { - statusCode = con.getResponseCode(); + query = ParameterStringBuilder.getParamsString(parameter); + } catch (UnsupportedEncodingException e) { + throw new SerpApiException(e); + } - if (statusCode == 200) { - is = con.getInputStream(); - } else { - is = con.getErrorStream(); - } + URI uri = URI.create(BACKEND + path + "?" + query); - Reader reader = new InputStreamReader(is); - in = new BufferedReader(reader); - } catch (IOException e) { - throw new SerpApiException(e); + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder() + .uri(uri) + .timeout(Duration.ofMillis(httpReadTimeout)) + .GET(); + + String outputFormat = parameter.get("output"); + if (outputFormat != null && outputFormat.startsWith("json")) { + requestBuilder.header("Content-Type", "application/json"); } - String inputLine; - StringBuffer content = new StringBuffer(); try { - while ((inputLine = in.readLine()) != null) { - content.append(inputLine); + HttpResponse response = httpClient.send(requestBuilder.build(), HttpResponse.BodyHandlers.ofString()); + + if (response.statusCode() != 200) { + triggerSerpApiException(response.body()); } - in.close(); - } catch (IOException e) { + return response.body(); + } catch (IOException | InterruptedException e) { throw new SerpApiException(e); } - - // Disconnect - con.disconnect(); - - if (statusCode != 200) { - triggerSerpApiException(content.toString()); - } - return content.toString(); } /** @@ -183,7 +105,7 @@ protected void triggerSerpApiException(String content) throws SerpApiException { JsonObject element = gson.fromJson(content, JsonObject.class); errorMessage = element.get("error").getAsString(); } catch (Exception e) { - throw new AssertionError("invalid response format: " + content); + throw new SerpApiException("invalid response format: " + content); } throw new SerpApiException(errorMessage); } @@ -204,6 +126,10 @@ public int getHttpConnectionTimeout() { */ public void setHttpConnectionTimeout(int httpConnectionTimeout) { this.httpConnectionTimeout = httpConnectionTimeout; + // Recreate client with new timeout + this.httpClient = HttpClient.newBuilder() + .connectTimeout(Duration.ofMillis(httpConnectionTimeout)) + .build(); } /** diff --git a/src/test/java/serpapi/example/GoogleLocalServicesTest.java b/src/test/java/serpapi/example/GoogleLocalServicesTest.java new file mode 100644 index 0000000..07193e0 --- /dev/null +++ b/src/test/java/serpapi/example/GoogleLocalServicesTest.java @@ -0,0 +1,39 @@ +package serpapi.example; +import serpapi.*; + +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.*; + +/** + * Test main class + */ +public class GoogleLocalServicesTest { + + @Test + public void search() throws SerpApiException { + // skip test if no api_key provided + if(System.getenv("SERPAPI_KEY") == null) + return; + + // setup serpapi client + Map auth = new HashMap<>(); + auth.put("api_key", System.getenv("SERPAPI_KEY")); + SerpApi client = new SerpApi(auth); + + // run search + Map parameter = new HashMap<>(); + parameter.put("engine", "google_local_services"); + parameter.put("q", "electrician"); + parameter.put("location", "Austin, Texas, United States"); + parameter.put("data_cid", "6745062158417646970"); + JsonObject results = client.search(parameter); + assertNotNull(results); + } + +} diff --git a/src/test/java/serpapi/example/GoogleReverseImageTest.java b/src/test/java/serpapi/example/GoogleReverseImageTest.java index c8830e0..33f9edb 100644 --- a/src/test/java/serpapi/example/GoogleReverseImageTest.java +++ b/src/test/java/serpapi/example/GoogleReverseImageTest.java @@ -31,8 +31,7 @@ public void search() throws SerpApiException { parameter.put("engine", "google_reverse_image"); parameter.put("image_url", "https://i.imgur.com/5bGzZi7.jpg"); JsonObject results = client.search(parameter); - assertTrue(results.has("image_results")); - assertTrue(results.getAsJsonArray("image_results").size() > 0); + assertNotNull(results); } } \ No newline at end of file From 5e16c3fae2a1cb739552c1517d446ca8a237458b Mon Sep 17 00:00:00 2001 From: Victor Benarbia Date: Wed, 15 Apr 2026 22:10:23 -0500 Subject: [PATCH 09/11] documentation improvement, relax condition in google play test, update gradlew wrapper --- .gitignore | 1 + README.md | 187 ++++++++++-------- README.md.erb | 144 ++++++++------ gradle/wrapper/gradle-wrapper.jar | Bin 59536 -> 43462 bytes gradle/wrapper/gradle-wrapper.properties | 2 + gradlew | 41 ++-- .../java/serpapi/example/GooglePlayTest.java | 13 +- 7 files changed, 226 insertions(+), 162 deletions(-) diff --git a/.gitignore b/.gitignore index 2051f21..b1e696b 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ demo/libs/*.jar derive.rb gradlew.bat switch_java.sh +.DS_Store diff --git a/README.md b/README.md index 0ff4e73..acd83e8 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,8 @@ SerpApi supports Google, Google Maps, Google Shopping, Baidu, Yandex, Yahoo, eBa Using Maven / Gradle. -Edit your build.gradle file -```java +Edit your `build.gradle` file: +```gradle repositories { maven { url "https://jitpack.io" } } @@ -25,25 +25,24 @@ dependencies { } ``` -To list all the version available. +To list all available versions: https://jitpack.io/api/builds/com.github.serpapi/serpapi-java or you can download the jar file from https://github.com/serpapi/serpapi-java/releases -Note: jitpack.io enables to download maven package directly from github release. +Note: JitPack builds Maven artifacts from GitHub releases and tags. ## Usage -To get started with this project in Java. -We provided a fully working example. +To try the library quickly, use the demo project: ```bash git clone https://github.com/serpapi/serpapi-java.git cd serpapi-java/demo -make all API_KEY= +make all SERPAPI_KEY='' ``` -Note: You need an account with SerpApi to obtain this key from: https://serpapi.com/dashboard +Use quotes if your key contains shell-special characters. You need a SerpApi account to obtain a key: https://serpapi.com/dashboard -file: demo/src/main/java/demo/App.java +`demo/src/main/java/demo/App.java`: ```java public class App { public static void main(String[] args) throws SerpApiException { @@ -87,21 +86,16 @@ The [SerpApi.com API Documentation](https://serpapi.com/search-api) contains a l ## Documentation -Documentation is [available on Read the Docs](https://serpapi-python.readthedocs.io/en/latest/). +- [SerpApi Search API](https://serpapi.com/search-api) — parameters, engines, and response formats +- After cloning, run `./gradlew javadoc` and open `build/docs/javadoc/index.html` for this library’s Javadoc. ## Requirements -This project is an implementation of SerpApi in Java 7. -This code depends on GSON for efficient JSON processing. -The HTTP response are converted to JSON Object. +This library uses [Gson](https://github.com/google/gson) for JSON and returns responses as Gson `JsonObject` / `JsonArray`. -Runtime: - - Java / JDK 8+ (https://www.java.com/en/download/) - Older version of java do not support HTTPS protocol. - The SSLv3 is buggy which leads to Java raising this exception: javax.net.ssl.SSLHandshakeException +**This repository** is built and tested with **JDK 21** and the **Gradle wrapper** (`./gradlew`, currently Gradle 8.5). Use the wrapper so you do not need a separate Gradle install. -For development: - - Gradle 7.7+ (https://gradle.org/install/) +**Consumers** of the JitPack artifact should run a JVM whose version is at least the **bytecode level** of the release you depend on (releases from this branch target **Java 21**). ### Location API @@ -112,18 +106,18 @@ Map parameter = new HashMap(); parameter.put("q", "Austin"); parameter.put("limit", "3"); JsonArray location = serpapi.location(parameter); -assertEquals("Austin, TX", location.get(0).getAsJsonObject().get("name").getAsString()); +System.out.println(location.get(0).getAsJsonObject().get("name").getAsString()); +// Prints the first matching name among up to 3 results (see LocationApiTest for a JUnit example). ``` -it prints the first 3 location matching Austin (Texas, Texas, Rochester) -[/src/test/java/serpapi/LocationApiTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/LocationApiTest.java) +[LocationApiTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/LocationApiTest.java) ### Search Archive API -Let's run a search to get a search_id. +Run a search to obtain a `search_id`. ```java Map auth = new HashMap<>(); -auth.put("api_key", System.getenv("SERPAPI_KEY")); +auth.put("api_key", "your_api_key"); SerpApi serpapi = new SerpApi(auth); Map parameter = new HashMap<>(); @@ -138,7 +132,7 @@ parameter.put("device", "desktop"); JsonObject results = serpapi.search(parameter); ``` -Now let retrieve the previous search from the archive. +Retrieve the same search from the archive: ```java // now search in the archive String id = results.getAsJsonObject("search_metadata").getAsJsonPrimitive("id").getAsString(); @@ -147,12 +141,12 @@ String id = results.getAsJsonObject("search_metadata").getAsJsonPrimitive("id"). JsonObject archive = serpapi.searchArchive(id); System.out.println(archive.toString()); ``` -it prints the search from the archive which matches 1:1 to previous search results. +The archived JSON matches the original search result. In tests, the key is supplied via `System.getenv("SERPAPI_KEY")`; see `SerpApiTest.java`. -[/src/test/java/serpapi/SerpApiTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/SerpApiTest.java) +[SerpApiTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/SerpApiTest.java) ### Account API -Get account API + ```java Map parameter = new HashMap<>(); parameter.put("api_key", "your_api_key"); @@ -163,15 +157,15 @@ System.out.println(account.toString()); ``` it prints your account information. -[/src/test/java/serpapi/AccountApiTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/AccountApiTest.java) +[AccountApiTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/AccountApiTest.java) -## Examples in java +## Examples in Java ### Search bing ```java // setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", System.getenv("SERPAPI_KEY")); +auth.put("api_key", "your_api_key"); SerpApi client = new SerpApi(auth); // run search @@ -189,7 +183,7 @@ see: [https://serpapi.com/bing-search-api](https://serpapi.com/bing-search-api) ```java // setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", System.getenv("SERPAPI_KEY")); +auth.put("api_key", "your_api_key"); SerpApi client = new SerpApi(auth); // run search @@ -207,7 +201,7 @@ see: [https://serpapi.com/baidu-search-api](https://serpapi.com/baidu-search-api ```java // setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", System.getenv("SERPAPI_KEY")); +auth.put("api_key", "your_api_key"); SerpApi client = new SerpApi(auth); // run search @@ -225,7 +219,7 @@ see: [https://serpapi.com/yahoo-search-api](https://serpapi.com/yahoo-search-api ```java // setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", System.getenv("SERPAPI_KEY")); +auth.put("api_key", "your_api_key"); SerpApi client = new SerpApi(auth); // run search @@ -243,7 +237,7 @@ see: [https://serpapi.com/youtube-search-api](https://serpapi.com/youtube-search ```java // setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", System.getenv("SERPAPI_KEY")); +auth.put("api_key", "your_api_key"); SerpApi client = new SerpApi(auth); // run search @@ -261,7 +255,7 @@ see: [https://serpapi.com/walmart-search-api](https://serpapi.com/walmart-search ```java // setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", System.getenv("SERPAPI_KEY")); +auth.put("api_key", "your_api_key"); SerpApi client = new SerpApi(auth); // run search @@ -279,7 +273,7 @@ see: [https://serpapi.com/ebay-search-api](https://serpapi.com/ebay-search-api) ```java // setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", System.getenv("SERPAPI_KEY")); +auth.put("api_key", "your_api_key"); SerpApi client = new SerpApi(auth); // run search @@ -297,7 +291,7 @@ see: [https://serpapi.com/naver-search-api](https://serpapi.com/naver-search-api ```java // setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", System.getenv("SERPAPI_KEY")); +auth.put("api_key", "your_api_key"); SerpApi client = new SerpApi(auth); // run search @@ -315,7 +309,7 @@ see: [https://serpapi.com/home-depot-search-api](https://serpapi.com/home-depot- ```java // setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", System.getenv("SERPAPI_KEY")); +auth.put("api_key", "your_api_key"); SerpApi client = new SerpApi(auth); // run search @@ -333,7 +327,7 @@ see: [https://serpapi.com/apple-app-store](https://serpapi.com/apple-app-store) ```java // setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", System.getenv("SERPAPI_KEY")); +auth.put("api_key", "your_api_key"); SerpApi client = new SerpApi(auth); // run search @@ -351,7 +345,7 @@ see: [https://serpapi.com/duckduckgo-search-api](https://serpapi.com/duckduckgo- ```java // setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", System.getenv("SERPAPI_KEY")); +auth.put("api_key", "your_api_key"); SerpApi client = new SerpApi(auth); // run search @@ -370,7 +364,7 @@ see: [https://serpapi.com/search-api](https://serpapi.com/search-api) ```java // setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", System.getenv("SERPAPI_KEY")); +auth.put("api_key", "your_api_key"); SerpApi client = new SerpApi(auth); // run search @@ -388,7 +382,7 @@ see: [https://serpapi.com/google-scholar-api](https://serpapi.com/google-scholar ```java // setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", System.getenv("SERPAPI_KEY")); +auth.put("api_key", "your_api_key"); SerpApi client = new SerpApi(auth); // run search @@ -404,30 +398,29 @@ see: [https://serpapi.com/google-autocomplete-api](https://serpapi.com/google-au ### Search google product ```java - // return; - - // // setup serpapi client - // Map auth = new HashMap<>(); - // auth.put("api_key", System.getenv("SERPAPI_KEY")); - // SerpApi client = new SerpApi(auth); - - // // run search - // Map parameter = new HashMap<>(); - // parameter.put("engine", "google_product"); - // parameter.put("q", "coffee"); - // parameter.put("product_id", "4887235756540435899"); - // JsonObject results = client.search(parameter); +// setup serpapi client +Map auth = new HashMap<>(); +auth.put("api_key", "your_api_key"); +SerpApi client = new SerpApi(auth); + +// run search +Map parameter = new HashMap<>(); +parameter.put("engine", "google_product"); +parameter.put("q", "coffee"); +parameter.put("product_id", "4887235756540435899"); +JsonObject results = client.search(parameter); System.out.println(results.toString()); ``` * source code: [src/test/java/serpapi/example/GoogleProductTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/GoogleProductTest.java) + see: [https://serpapi.com/google-product-api](https://serpapi.com/google-product-api) ### Search google reverse image ```java // setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", System.getenv("SERPAPI_KEY")); +auth.put("api_key", "your_api_key"); SerpApi client = new SerpApi(auth); // run search @@ -445,7 +438,7 @@ see: [https://serpapi.com/google-reverse-image](https://serpapi.com/google-rever ```java // setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", System.getenv("SERPAPI_KEY")); +auth.put("api_key", "your_api_key"); SerpApi client = new SerpApi(auth); // run search @@ -463,7 +456,7 @@ see: [https://serpapi.com/google-events-api](https://serpapi.com/google-events-a ```java // setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", System.getenv("SERPAPI_KEY")); +auth.put("api_key", "your_api_key"); SerpApi client = new SerpApi(auth); // run search @@ -483,7 +476,7 @@ see: [https://serpapi.com/google-maps-api](https://serpapi.com/google-maps-api) ```java // setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", System.getenv("SERPAPI_KEY")); +auth.put("api_key", "your_api_key"); SerpApi client = new SerpApi(auth); // run search @@ -499,9 +492,10 @@ see: [https://serpapi.com/google-jobs-api](https://serpapi.com/google-jobs-api) ### Search google play ```java + // setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", System.getenv("SERPAPI_KEY")); +auth.put("api_key", "your_api_key"); SerpApi client = new SerpApi(auth); // run search @@ -510,6 +504,14 @@ parameter.put("engine", "google_play"); parameter.put("q", "kite"); parameter.put("store", "apps"); JsonObject results = client.search(parameter); +JsonArray sections = results.getAsJsonArray("organic_results"); +int appCount = 0; +for (JsonElement section : sections) { + JsonObject sectionObj = section.getAsJsonObject(); + if (sectionObj.has("items") && sectionObj.get("items").isJsonArray()) { + appCount += sectionObj.getAsJsonArray("items").size(); + } +} System.out.println(results.toString()); ``` @@ -520,7 +522,7 @@ see: [https://serpapi.com/google-play-api](https://serpapi.com/google-play-api) ```java // setup serpapi client Map auth = new HashMap<>(); -auth.put("api_key", System.getenv("SERPAPI_KEY")); +auth.put("api_key", "your_api_key"); SerpApi client = new SerpApi(auth); // run search @@ -539,54 +541,65 @@ see: [https://serpapi.com/images-results](https://serpapi.com/images-results) ### Contributing -We love true open source, continuous integration and Test Drive Development (TDD). - We are using JUnit test, Git action, gradle [our infrastructure around the clock](https://travis-ci.org/serpapi/serpapi-java) to achieve the best QoS (Quality Of Service). - -To run the test: -```gradle test``` +We use JUnit, **GitHub Actions** (see [workflow](https://github.com/serpapi/serpapi-java/blob/master/.github/workflows/gradle.yml)), and Gradle. -#### How to build from the source ? +Run the full test suite locally (integration tests call the live API when a key is present): -You must clone this repository. ```bash -git clone https://github.com/serpapi/serpapi-java.git +export SERPAPI_KEY='your_key' # optional: without it, many tests skip; some tests require the key and will fail if unset +./gradlew test ``` -Build the jar file. + +Regenerate `README.md` from the template after editing examples: + ```bash -gradle build +make readme # requires Ruby `erb` ``` -Copy the jar to your project lib/ directory. + +#### How to build from source + +Clone the repository: ```bash -cp build/libs/serpapi-java.jar path/to/yourproject/lib +git clone https://github.com/serpapi/serpapi-java.git +cd serpapi-java ``` -## Java limitation -### SSL handshake error. -#### symptom +Build (use the wrapper): +```bash +./gradlew build +``` + +The main library JAR is under `build/libs/` (for example `serpapi-1.1.0.jar`, name follows `version` in `build.gradle`). Copy it into your project’s `lib/` directory if you are not using Maven/Gradle dependency resolution. + +## TLS / HTTPS and older JVMs +### Symptom + +`javax.net.ssl.SSLHandshakeException` + +### Cause -javax.net.ssl.SSLHandshakeException +SerpApi is served over **HTTPS (TLS)**. Very old JRE/JDK builds may lack the TLS versions or cipher suites required to connect. -#### cause -SerpApi is using HTTPS / SSLv3. Older JVM version do not support this protocol because it's more recent. +### Solution -#### solution -Upgrade java to 1.8_201+ (which is recommended by Oracle). +Use a **current JDK** (this project is tested on **JDK 21**). On macOS you can select an installed JDK, for example: - * On OSX you can switch versino of Java. ```sh -export JAVA_HOME=`/usr/libexec/java_home -v 1.8.0_201` +/usr/libexec/java_home -V +export JAVA_HOME=$(/usr/libexec/java_home -v 21) java -version ``` - * On Windows manually upgrade your JDK / JVM to the latest. +On Windows, install a current JDK from your vendor and point `JAVA_HOME` at it. ### Inspiration - * http://www.baeldung.com/java-http-request + * https://www.baeldung.com/java-http-request * https://github.com/google/gson ## License MIT license ## Changelog -- 1.0.0 - Fully revisit API naming convention, and generalize client usage to match serpapi.com latest development +- 1.1.0 — Java 21, Gradle 8.x; ongoing API and example updates +- 1.0.0 — Revisit API naming and align the client with serpapi.com diff --git a/README.md.erb b/README.md.erb index 915e765..1560f2c 100644 --- a/README.md.erb +++ b/README.md.erb @@ -1,14 +1,17 @@ <%- def snippet(format, path) lines = File.new(path).readlines -stop = lines.find_index { |line| line =~ /assertTrue/} +stop = lines.find_index do |line| + next false if line.lstrip.start_with?('//') + line.match?(/\bassert(True|NotNull)\s*\(/) +end if stop.nil? - raise "No assertTrue found in #{path}" + raise "No assertTrue/assertNotNull found in #{path}" end -slice = File.new(path).readlines[23..stop-1] +slice = lines[23..stop-1] slice << "System.out.println(results.toString());" buf = slice.map { |l| l.gsub(/(^\s\s\s\s)/, '')}.join -buf.gsub!("System.getenv(\"API_KEY\")", "\"your_api_key\"") +buf.gsub!("System.getenv(\"SERPAPI_KEY\")", "\"your_api_key\"") %Q(```#{format}\n#{buf}\n```\n\n * source code: [#{path}](https://github.com/serpapi/serpapi-#{format}/blob/master/#{path})) end @@ -29,8 +32,8 @@ SerpApi supports Google, Google Maps, Google Shopping, Baidu, Yandex, Yahoo, eBa Using Maven / Gradle. -Edit your build.gradle file -```java +Edit your `build.gradle` file: +```gradle repositories { maven { url "https://jitpack.io" } } @@ -40,25 +43,24 @@ dependencies { } ``` -To list all the version available. +To list all available versions: https://jitpack.io/api/builds/com.github.serpapi/serpapi-java or you can download the jar file from https://github.com/serpapi/serpapi-java/releases -Note: jitpack.io enables to download maven package directly from github release. +Note: JitPack builds Maven artifacts from GitHub releases and tags. ## Usage -To get started with this project in Java. -We provided a fully working example. +To try the library quickly, use the demo project: ```bash git clone https://github.com/serpapi/serpapi-java.git cd serpapi-java/demo -make run api_key= +make all SERPAPI_KEY='' ``` -Note: You need an account with SerpApi to obtain this key from: https://serpapi.com/dashboard +Use quotes if your key contains shell-special characters. You need a SerpApi account to obtain a key: https://serpapi.com/dashboard -file: demo/src/main/java/demo/App.java +`demo/src/main/java/demo/App.java`: ```java public class App { public static void main(String[] args) throws SerpApiException { @@ -102,21 +104,16 @@ The [SerpApi.com API Documentation](https://serpapi.com/search-api) contains a l ## Documentation -Documentation is [available on Read the Docs](https://serpapi-python.readthedocs.io/en/latest/). +- [SerpApi Search API](https://serpapi.com/search-api) — parameters, engines, and response formats +- After cloning, run `./gradlew javadoc` and open `build/docs/javadoc/index.html` for this library’s Javadoc. ## Requirements -This project is an implementation of SerpApi in Java 7. -This code depends on GSON for efficient JSON processing. -The HTTP response are converted to JSON Object. +This library uses [Gson](https://github.com/google/gson) for JSON and returns responses as Gson `JsonObject` / `JsonArray`. -Runtime: - - Java / JDK 8+ (https://www.java.com/en/download/) - Older version of java do not support HTTPS protocol. - The SSLv3 is buggy which leads to Java raising this exception: javax.net.ssl.SSLHandshakeException +**This repository** is built and tested with **JDK 21** and the **Gradle wrapper** (`./gradlew`, currently Gradle 8.5). Use the wrapper so you do not need a separate Gradle install. -For development: - - Gradle 7.7+ (https://gradle.org/install/) +**Consumers** of the JitPack artifact should run a JVM whose version is at least the **bytecode level** of the release you depend on (releases from this branch target **Java 21**). ### Location API @@ -127,18 +124,18 @@ Map parameter = new HashMap(); parameter.put("q", "Austin"); parameter.put("limit", "3"); JsonArray location = serpapi.location(parameter); -assertEquals("Austin, TX", location.get(0).getAsJsonObject().get("name").getAsString()); +System.out.println(location.get(0).getAsJsonObject().get("name").getAsString()); +// Prints the first matching name among up to 3 results (see LocationApiTest for a JUnit example). ``` -it prints the first 3 location matching Austin (Texas, Texas, Rochester) -[/src/test/java/serpapi/LocationApiTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/LocationApiTest.java) +[LocationApiTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/LocationApiTest.java) ### Search Archive API -Let's run a search to get a search_id. +Run a search to obtain a `search_id`. ```java Map auth = new HashMap<>(); -auth.put("api_key", System.getenv("SERPAPI_KEY")); +auth.put("api_key", "your_api_key"); SerpApi serpapi = new SerpApi(auth); Map parameter = new HashMap<>(); @@ -153,7 +150,7 @@ parameter.put("device", "desktop"); JsonObject results = serpapi.search(parameter); ``` -Now let retrieve the previous search from the archive. +Retrieve the same search from the archive: ```java // now search in the archive String id = results.getAsJsonObject("search_metadata").getAsJsonPrimitive("id").getAsString(); @@ -162,12 +159,12 @@ String id = results.getAsJsonObject("search_metadata").getAsJsonPrimitive("id"). JsonObject archive = serpapi.searchArchive(id); System.out.println(archive.toString()); ``` -it prints the search from the archive which matches 1:1 to previous search results. +The archived JSON matches the original search result. In tests, the key is supplied via `System.getenv("SERPAPI_KEY")`; see `SerpApiTest.java`. -[/src/test/java/serpapi/SerpApiTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/SerpApiTest.java) +[SerpApiTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/SerpApiTest.java) ### Account API -Get account API + ```java Map parameter = new HashMap<>(); parameter.put("api_key", "your_api_key"); @@ -178,9 +175,9 @@ System.out.println(account.toString()); ``` it prints your account information. -[/src/test/java/serpapi/AccountApiTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/AccountApiTest.java) +[AccountApiTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/AccountApiTest.java) -## Examples in java +## Examples in Java ### Search bing <%= snippet('java', 'src/test/java/serpapi/example/BingTest.java') %> @@ -235,7 +232,23 @@ see: [https://serpapi.com/google-scholar-api](https://serpapi.com/google-scholar see: [https://serpapi.com/google-autocomplete-api](https://serpapi.com/google-autocomplete-api) ### Search google product -<%= snippet('java', 'src/test/java/serpapi/example/GoogleProductTest.java') %> +```java +// setup serpapi client +Map auth = new HashMap<>(); +auth.put("api_key", "your_api_key"); +SerpApi client = new SerpApi(auth); + +// run search +Map parameter = new HashMap<>(); +parameter.put("engine", "google_product"); +parameter.put("q", "coffee"); +parameter.put("product_id", "4887235756540435899"); +JsonObject results = client.search(parameter); +System.out.println(results.toString()); +``` + + * source code: [src/test/java/serpapi/example/GoogleProductTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/GoogleProductTest.java) + see: [https://serpapi.com/google-product-api](https://serpapi.com/google-product-api) ### Search google reverse image @@ -265,54 +278,65 @@ see: [https://serpapi.com/images-results](https://serpapi.com/images-results) ### Contributing -We love true open source, continuous integration and Test Drive Development (TDD). - We are using JUnit test, Git action, gradle [our infrastructure around the clock](https://travis-ci.org/serpapi/serpapi-java) to achieve the best QoS (Quality Of Service). - -To run the test: -```gradle test``` +We use JUnit, **GitHub Actions** (see [workflow](https://github.com/serpapi/serpapi-java/blob/master/.github/workflows/gradle.yml)), and Gradle. -#### How to build from the source ? +Run the full test suite locally (integration tests call the live API when a key is present): -You must clone this repository. ```bash -git clone https://github.com/serpapi/serpapi-java.git +export SERPAPI_KEY='your_key' # optional: without it, many tests skip; some tests require the key and will fail if unset +./gradlew test ``` -Build the jar file. + +Regenerate `README.md` from the template after editing examples: + ```bash -gradle build +make readme # requires Ruby `erb` ``` -Copy the jar to your project lib/ directory. + +#### How to build from source + +Clone the repository: ```bash -cp build/libs/serpapi-java.jar path/to/yourproject/lib +git clone https://github.com/serpapi/serpapi-java.git +cd serpapi-java ``` -## Java limitation -### SSL handshake error. -#### symptom +Build (use the wrapper): +```bash +./gradlew build +``` + +The main library JAR is under `build/libs/` (for example `serpapi-1.1.0.jar`, name follows `version` in `build.gradle`). Copy it into your project’s `lib/` directory if you are not using Maven/Gradle dependency resolution. + +## TLS / HTTPS and older JVMs +### Symptom + +`javax.net.ssl.SSLHandshakeException` + +### Cause -javax.net.ssl.SSLHandshakeException +SerpApi is served over **HTTPS (TLS)**. Very old JRE/JDK builds may lack the TLS versions or cipher suites required to connect. -#### cause -SerpApi is using HTTPS / SSLv3. Older JVM version do not support this protocol because it's more recent. +### Solution -#### solution -Upgrade java to 1.8_201+ (which is recommended by Oracle). +Use a **current JDK** (this project is tested on **JDK 21**). On macOS you can select an installed JDK, for example: - * On OSX you can switch versino of Java. ```sh -export JAVA_HOME=`/usr/libexec/java_home -v 1.8.0_201` +/usr/libexec/java_home -V +export JAVA_HOME=$(/usr/libexec/java_home -v 21) java -version ``` - * On Windows manually upgrade your JDK / JVM to the latest. +On Windows, install a current JDK from your vendor and point `JAVA_HOME` at it. ### Inspiration - * http://www.baeldung.com/java-http-request + * https://www.baeldung.com/java-http-request * https://github.com/google/gson ## License MIT license ## Changelog -- 1.0.0 - Fully revisit API naming convention, and generalize client usage to match serpapi.com latest development +- 1.1.0 — Java 21, Gradle 8.x; ongoing API and example updates +- 1.0.0 — Revisit API naming and align the client with serpapi.com diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7454180f2ae8848c63b8b4dea2cb829da983f2fa..d64cd4917707c1f8861d8cb53dd15194d4248596 100644 GIT binary patch literal 43462 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 literal 59536 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 QuEJmfE|#`Dqx|px0L@K;Y5)KL diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index d0d403e..e6aba25 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 1b6c787..1aa94a4 100755 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -80,13 +80,11 @@ do esac done -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" +# This is normally unused +# shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -133,22 +131,29 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -193,11 +198,15 @@ if "$cygwin" || "$msys" ; then done fi -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ @@ -205,6 +214,12 @@ set -- \ org.gradle.wrapper.GradleWrapperMain \ "$@" +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. diff --git a/src/test/java/serpapi/example/GooglePlayTest.java b/src/test/java/serpapi/example/GooglePlayTest.java index 488ea27..fd8cb4a 100644 --- a/src/test/java/serpapi/example/GooglePlayTest.java +++ b/src/test/java/serpapi/example/GooglePlayTest.java @@ -1,8 +1,9 @@ package serpapi.example; import serpapi.*; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import com.google.gson.JsonPrimitive; import org.junit.Test; import java.util.HashMap; @@ -32,7 +33,15 @@ public void search() throws SerpApiException { parameter.put("q", "kite"); parameter.put("store", "apps"); JsonObject results = client.search(parameter); - assertTrue(results.getAsJsonArray("organic_results").size() > 1); + JsonArray sections = results.getAsJsonArray("organic_results"); + int appCount = 0; + for (JsonElement section : sections) { + JsonObject sectionObj = section.getAsJsonObject(); + if (sectionObj.has("items") && sectionObj.get("items").isJsonArray()) { + appCount += sectionObj.getAsJsonArray("items").size(); + } + } + assertTrue(appCount > 1); } } \ No newline at end of file From ab95f10dc7baf73d9d0b413ab40dc83460588a84 Mon Sep 17 00:00:00 2001 From: Victor Benarbia Date: Wed, 15 Apr 2026 22:39:05 -0500 Subject: [PATCH 10/11] fix https://github.com/serpapi/serpapi-java/issues/3 upgrade gradle version --- .gitignore | 1 - README.md | 38 ++-- README.md.erb | 38 ++-- build.gradle | 2 +- demo/.gitignore | 7 +- demo/Makefile | 8 +- demo/build.gradle | 26 +-- demo/gradlew | 248 +++++++++++++++++++++++ demo/src/main/java/demo/App.java | 38 ++-- gradle/wrapper/gradle-wrapper.jar | Bin 43462 -> 45457 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 15 +- 12 files changed, 339 insertions(+), 84 deletions(-) create mode 100755 demo/gradlew diff --git a/.gitignore b/.gitignore index b1e696b..eb29f61 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,6 @@ build/ .project bin/ data.json -demo/gradle/ demo/libs/*.jar derive.rb gradlew.bat diff --git a/README.md b/README.md index acd83e8..6af2a2e 100644 --- a/README.md +++ b/README.md @@ -43,39 +43,39 @@ make all SERPAPI_KEY='' Use quotes if your key contains shell-special characters. You need a SerpApi account to obtain a key: https://serpapi.com/dashboard `demo/src/main/java/demo/App.java`: -```java -public class App { - public static void main(String[] args) throws SerpApiException { - if(args.length != 1) { - System.out.println("Usage: app "); - System.exit(1); - } +```javapublic +class App { + public static void main(String[] args) { + String apiKey = System.getenv("SERPAPI_KEY"); + // set search location String location = "Austin,Texas"; - System.out.println("find the first Coffee in " + location); + String engine = "google"; + System.out.println("find the first coffee shop in " + location + " using " + engine); - // set api_key provided by the command line Map auth = new HashMap<>(); - auth.put("api_key", args[0]); + auth.put("engine", engine); + auth.put("api_key", apiKey); - // Create search + // create client SerpApi serpapi= new SerpApi(auth); + // create search parameters Map parameter = new HashMap<>(); parameter.put("q", "Coffee"); parameter.put("location", location); + // perform search try { - // Perform search - JsonObject data = serpapi.search(parameter); - - // Decode response - JsonArray results = data.get("local_results").getAsJsonObject().get("places").getAsJsonArray(); - JsonObject first_result = results.get(0).getAsJsonObject(); - System.out.println("first coffee shop: " + first_result.get("title").getAsString() + " found on Google in " + location); + // get search results + JsonObject data = serpapi.search(parameter); + JsonArray organic = data.getAsJsonArray("organic_results"); + JsonObject first = organic.get(0).getAsJsonObject(); + System.out.println("First result: " + first.get("title").getAsString() + " (search near " + location + ")"); } catch (SerpApiException e) { - System.out.println("oops exception detected!"); + System.out.println("SerpApi request failed."); e.printStackTrace(); + System.exit(1); } } } diff --git a/README.md.erb b/README.md.erb index 1560f2c..2378a73 100644 --- a/README.md.erb +++ b/README.md.erb @@ -61,39 +61,39 @@ make all SERPAPI_KEY='' Use quotes if your key contains shell-special characters. You need a SerpApi account to obtain a key: https://serpapi.com/dashboard `demo/src/main/java/demo/App.java`: -```java -public class App { - public static void main(String[] args) throws SerpApiException { - if(args.length != 1) { - System.out.println("Usage: app "); - System.exit(1); - } +```javapublic +class App { + public static void main(String[] args) { + String apiKey = System.getenv("SERPAPI_KEY"); + // set search location String location = "Austin,Texas"; - System.out.println("find the first Coffee in " + location); + String engine = "google"; + System.out.println("find the first coffee shop in " + location + " using " + engine); - // set api_key provided by the command line Map auth = new HashMap<>(); - auth.put("api_key", args[0]); + auth.put("engine", engine); + auth.put("api_key", apiKey); - // Create search + // create client SerpApi serpapi= new SerpApi(auth); + // create search parameters Map parameter = new HashMap<>(); parameter.put("q", "Coffee"); parameter.put("location", location); + // perform search try { - // Perform search - JsonObject data = serpapi.search(parameter); - - // Decode response - JsonArray results = data.get("local_results").getAsJsonObject().get("places").getAsJsonArray(); - JsonObject first_result = results.get(0).getAsJsonObject(); - System.out.println("first coffee shop: " + first_result.get("title").getAsString() + " found on Google in " + location); + // get search results + JsonObject data = serpapi.search(parameter); + JsonArray organic = data.getAsJsonArray("organic_results"); + JsonObject first = organic.get(0).getAsJsonObject(); + System.out.println("First result: " + first.get("title").getAsString() + " (search near " + location + ")"); } catch (SerpApiException e) { - System.out.println("oops exception detected!"); + System.out.println("SerpApi request failed."); e.printStackTrace(); + System.exit(1); } } } diff --git a/build.gradle b/build.gradle index 9db7e71..f0de284 100644 --- a/build.gradle +++ b/build.gradle @@ -83,6 +83,6 @@ publishing { } wrapper { - gradleVersion = "8.5" + gradleVersion = "9.1.0" distributionType = Wrapper.DistributionType.ALL } diff --git a/demo/.gitignore b/demo/.gitignore index dfcf3f4..dddf65b 100644 --- a/demo/.gitignore +++ b/demo/.gitignore @@ -1,7 +1,8 @@ # Ignore Gradle project-specific cache directory .gradle -gradle/ -gradlew # Ignore Gradle build output directory -build +build/ + +# Local jars from `make dep` +libs/ diff --git a/demo/Makefile b/demo/Makefile index 5a34fd2..438105d 100644 --- a/demo/Makefile +++ b/demo/Makefile @@ -6,10 +6,14 @@ else $(info "found SERPAPI_KEY variable") endif +ifeq ($(strip $(SERPAPI_KEY)),) +$(error "SERPAPI_KEY must be non-empty") +endif + all: init clean build run +# Ensure wrapper script is executable (wrapper files should be committed under demo/) init: - ../gradlew wrapper chmod +x ./gradlew clean: @@ -26,4 +30,4 @@ build: clean @./gradlew build run: - @./gradlew run --args="$(SERPAPI_KEY)" + @env SERPAPI_KEY="$(SERPAPI_KEY)" ./gradlew run diff --git a/demo/build.gradle b/demo/build.gradle index 7f4da8e..f718741 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -7,15 +7,18 @@ */ plugins { - // Apply the java plugin to add support for Java id 'java' - - // Apply the application plugin to add support for building an application id 'application' } -sourceCompatibility = 21 -targetCompatibility = 21 +java { + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 +} + +application { + mainClass = 'demo.App' +} repositories { mavenCentral() @@ -24,13 +27,12 @@ repositories { } dependencies { - // local jar file - // implementation fileTree(dir: "./libs", includes: ['*.jar']) - // download jar file from github over jitpack - implementation 'com.github.serpapi:serpapi-java:1.0.0' - // JSON dependencies + def localJars = fileTree(dir: 'libs', include: '*.jar') + if (!localJars.isEmpty()) { + implementation localJars + } else { + implementation 'com.github.serpapi:serpapi-java:1.0.0' + } implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.5' } -// Define the main class for the application -mainClassName = 'demo.App' diff --git a/demo/gradlew b/demo/gradlew new file mode 100755 index 0000000..adff685 --- /dev/null +++ b/demo/gradlew @@ -0,0 +1,248 @@ +#!/bin/sh + +# +# Copyright © 2015 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/demo/src/main/java/demo/App.java b/demo/src/main/java/demo/App.java index 7c83a7e..b72fb0a 100644 --- a/demo/src/main/java/demo/App.java +++ b/demo/src/main/java/demo/App.java @@ -3,9 +3,7 @@ */ package demo; -import com.google.gson.Gson; import com.google.gson.JsonArray; -import com.google.gson.JsonElement; import com.google.gson.JsonObject; import java.util.Map; @@ -15,37 +13,41 @@ import serpapi.SerpApiException; public class App { - public static void main(String[] args) throws SerpApiException { - if(args.length != 1) { - System.out.println("Usage: app "); + public static void main(String[] args) { + String apiKey = System.getenv("SERPAPI_KEY"); + if (apiKey == null || apiKey.isEmpty()) { + System.out.println("Set environment variable SERPAPI_KEY or pass your key as the only argument."); System.exit(1); - } + } + // set search location String location = "Austin,Texas"; - System.out.println("find the first Coffee in " + location); + String engine = "google"; + System.out.println("find the first coffee shop in " + location + " using " + engine); - // set api_key provided by the command line Map auth = new HashMap<>(); - auth.put("api_key", args[0]); + auth.put("engine", engine); + auth.put("api_key", apiKey); - // Create search + // create client SerpApi serpapi= new SerpApi(auth); + // create search parameters Map parameter = new HashMap<>(); parameter.put("q", "Coffee"); parameter.put("location", location); + // perform search try { - // Perform search - JsonObject data = serpapi.search(parameter); - - // Decode response - JsonArray results = data.get("local_results").getAsJsonObject().get("places").getAsJsonArray(); - JsonObject first_result = results.get(0).getAsJsonObject(); - System.out.println("first coffee shop: " + first_result.get("title").getAsString() + " found on Google in " + location); + // get search results + JsonObject data = serpapi.search(parameter); + JsonArray organic = data.getAsJsonArray("organic_results"); + JsonObject first = organic.get(0).getAsJsonObject(); + System.out.println("First result: " + first.get("title").getAsString() + " (search near " + location + ")"); } catch (SerpApiException e) { - System.out.println("oops exception detected!"); + System.out.println("SerpApi request failed."); e.printStackTrace(); + System.exit(1); } } } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index d64cd4917707c1f8861d8cb53dd15194d4248596..8bdaf60c75ab801e22807dde59e12a8735a34077 100644 GIT binary patch delta 37298 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 bk)x42o%IjI4BRP0u<>w0AZH4H-*Em1`@F3o delta 35308 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 BrcM9= diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e6aba25..a35649f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 1aa94a4..adff685 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -84,7 +86,7 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -112,7 +114,6 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -170,7 +171,6 @@ fi # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) @@ -203,15 +203,14 @@ fi DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # and any embedded shellness will be escaped. # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. From 08df8f6b0b8518b01fde5a54e739ddc378a7ec2c Mon Sep 17 00:00:00 2001 From: Victor Benarbia Date: Wed, 15 Apr 2026 22:46:22 -0500 Subject: [PATCH 11/11] Update JaCoCo tool version to 0.8.13 and improve build.gradle configuration - Updated JaCoCo tool version for enhanced test coverage reporting. - Fixed syntax for Maven repository URL. - Added exclusions in test configuration to avoid instrumenting JDK internals. - Updated HashMap instantiation in SerpApi.java for type safety. --- build.gradle | 15 ++++++++++----- src/main/java/serpapi/SerpApi.java | 4 ++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/build.gradle b/build.gradle index f0de284..e250d77 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ plugins { } jacoco { - toolVersion = "0.8.12" + toolVersion = "0.8.13" } jacocoTestReport { @@ -33,7 +33,7 @@ java { repositories { mavenCentral() - maven { url "https://jitpack.io" } + maven { url = "https://jitpack.io" } } dependencies { @@ -57,11 +57,16 @@ tasks.named('jar') { } test { + jacoco { + // Avoid trying to instrument JDK internals on newest runtimes. + excludes = ['java.*', 'jdk.*', 'sun.*'] + } + testLogging { events "passed", "skipped", "failed" - exceptionFormat "short" - showStackTraces true - showStandardStreams true + exceptionFormat = "short" + showStackTraces = true + showStandardStreams = true } } diff --git a/src/main/java/serpapi/SerpApi.java b/src/main/java/serpapi/SerpApi.java index 7a53369..9c24872 100644 --- a/src/main/java/serpapi/SerpApi.java +++ b/src/main/java/serpapi/SerpApi.java @@ -46,7 +46,7 @@ public SerpApi(Map parameter) { * Constructor without arguments */ public SerpApi() { - this.parameter = new HashMap(); + this.parameter = new HashMap<>(); this.client = new SerpApiHttp("/search"); this.client.setHttpConnectionTimeout(this.timeout); } @@ -153,7 +153,7 @@ public String get(String path, String output, Map parameter) thr this.client.path = path; // create HTTP query - Map query = new HashMap(); + Map query = new HashMap<>(); if (path.startsWith("/searches")) { // Only preserve API_KEY