-
Notifications
You must be signed in to change notification settings - Fork 209
New Adapter: Sparteo #3985
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
New Adapter: Sparteo #3985
Conversation
52058a2
to
bf1549b
Compare
bf1549b
to
70b88dd
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please make sure the Go and Java versions have feature parity before merging
src/main/java/org/prebid/server/bidder/sparteo/SparteoBidder.java
Outdated
Show resolved
Hide resolved
src/main/java/org/prebid/server/bidder/sparteo/SparteoBidder.java
Outdated
Show resolved
Hide resolved
src/main/java/org/prebid/server/bidder/sparteo/SparteoBidder.java
Outdated
Show resolved
Hide resolved
src/main/java/org/prebid/server/bidder/sparteo/SparteoBidder.java
Outdated
Show resolved
Hide resolved
src/main/java/org/prebid/server/bidder/sparteo/SparteoBidder.java
Outdated
Show resolved
Hide resolved
src/main/java/org/prebid/server/proto/openrtb/ext/request/sparteo/ExtImpSparteo.java
Outdated
Show resolved
Hide resolved
Hi @AntoxaAntoxic , |
src/main/java/org/prebid/server/bidder/sparteo/SparteoBidder.java
Outdated
Show resolved
Hide resolved
src/main/java/org/prebid/server/bidder/sparteo/SparteoBidder.java
Outdated
Show resolved
Hide resolved
src/main/java/org/prebid/server/bidder/sparteo/SparteoBidder.java
Outdated
Show resolved
Hide resolved
src/main/java/org/prebid/server/bidder/sparteo/SparteoBidder.java
Outdated
Show resolved
Hide resolved
src/main/java/org/prebid/server/bidder/sparteo/SparteoBidder.java
Outdated
Show resolved
Hide resolved
src/main/java/org/prebid/server/bidder/sparteo/SparteoBidder.java
Outdated
Show resolved
Hide resolved
src/main/java/org/prebid/server/bidder/sparteo/SparteoBidder.java
Outdated
Show resolved
Hide resolved
src/main/java/org/prebid/server/bidder/sparteo/SparteoBidder.java
Outdated
Show resolved
Hide resolved
src/main/java/org/prebid/server/bidder/sparteo/SparteoBidder.java
Outdated
Show resolved
Hide resolved
)) | ||
.willReturn(aResponse().withBody( | ||
jsonFrom("openrtb2/sparteo/test-sparteo-bid-response.json") | ||
))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
closing parenthesis shouldn't be on the new line, please check the code style guide and fix everywhere
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Formatted
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not fixed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated
public Result<List<HttpRequest<BidRequest>>> makeHttpRequests(BidRequest request) { | ||
final List<BidderError> errors = new ArrayList<>(); | ||
final List<Imp> modifiedImps = new ArrayList<>(); | ||
String siteNetworkId = null; | ||
|
||
for (Imp imp : request.getImp()) { | ||
try { | ||
final ObjectNode impExt = mapper.mapper().convertValue(imp.getExt(), ObjectNode.class); | ||
|
||
final JsonNode bidderNode = impExt.get("bidder"); | ||
final ExtImpSparteo bidderParams = mapper.mapper().treeToValue(bidderNode, ExtImpSparteo.class); | ||
|
||
if (siteNetworkId == null && bidderParams.getNetworkId() != null) { | ||
siteNetworkId = bidderParams.getNetworkId(); | ||
} | ||
|
||
final ObjectNode modifiedExt = buildImpExt(impExt, bidderParams, mapper); | ||
|
||
modifiedImps.add(imp.toBuilder().ext(modifiedExt).build()); | ||
} catch (JsonProcessingException e) { | ||
errors.add(BidderError.badInput( | ||
"ignoring imp id=%s, error processing ext: %s".formatted( | ||
imp.getId(), e.getMessage()))); | ||
} | ||
} | ||
|
||
if (modifiedImps.isEmpty()) { | ||
return Result.withErrors(errors); | ||
} | ||
|
||
final BidRequest outgoingRequest = request.toBuilder() | ||
.imp(modifiedImps) | ||
.site(modifySite(request.getSite(), siteNetworkId, mapper)) | ||
.build(); | ||
|
||
final HttpRequest<BidRequest> call = BidderUtil.defaultRequest(outgoingRequest, endpointUrl, mapper); | ||
|
||
return Result.of(Collections.singletonList(call), errors); | ||
} | ||
|
||
private ObjectNode buildImpExt(ObjectNode impExt, ExtImpSparteo bidderParams, JacksonMapper mapper) | ||
throws JsonProcessingException { | ||
|
||
final String adUnitCode = Optional.ofNullable(impExt.get("prebid")) | ||
.map(prebidNode -> prebidNode.get("adunitcode")) | ||
.filter(JsonNode::isTextual) | ||
.map(JsonNode::asText) | ||
.orElse(null); | ||
|
||
final Map<String, JsonNode> sparteoProperties = Optional.ofNullable(impExt.get("sparteo")) | ||
.map(sparteoNode -> sparteoNode.get("params")) | ||
.filter(JsonNode::isObject) | ||
.map(paramsNode -> mapper.mapper().convertValue(paramsNode, | ||
new TypeReference<Map<String, JsonNode>>() { })) | ||
.orElse(Collections.emptyMap()); | ||
|
||
final Map<String, JsonNode> additionnalProperties = new HashMap<>(sparteoProperties); | ||
additionnalProperties.putAll(bidderParams.getAdditionalProperties()); | ||
|
||
final ExtImpParamsSparteo sparteoParams = ExtImpParamsSparteo.of( | ||
bidderParams.getNetworkId(), | ||
bidderParams.getCustom1(), | ||
bidderParams.getCustom2(), | ||
bidderParams.getCustom3(), | ||
bidderParams.getCustom4(), | ||
bidderParams.getCustom5(), | ||
adUnitCode, | ||
additionnalProperties); | ||
|
||
final ObjectNode ext = mapper.mapper().createObjectNode(); | ||
|
||
impExt.fields().forEachRemaining(entry -> { | ||
final String key = entry.getKey(); | ||
if (!key.equals("bidder") && !key.equals("sparteo")) { | ||
ext.set(key, entry.getValue()); | ||
} | ||
}); | ||
|
||
final ObjectNode sparteoParamsAsNode = mapper.mapper().convertValue(sparteoParams, ObjectNode.class); | ||
ext.putObject("sparteo").set("params", sparteoParamsAsNode); | ||
|
||
return ext; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay, spent some time on refactoring, here is what I came up with
private static final TypeReference<ExtPrebid<?, ExtImpSparteo>> TYPE_REFERENCE =
new TypeReference<>() {
};
private final String endpointUrl;
private final JacksonMapper mapper;
public SparteoBidder(String endpointUrl, JacksonMapper mapper) {
this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl));
this.mapper = Objects.requireNonNull(mapper);
}
@Override
public Result<List<HttpRequest<BidRequest>>> makeHttpRequests(BidRequest request) {
final List<BidderError> errors = new ArrayList<>();
final List<Imp> modifiedImps = new ArrayList<>();
String siteNetworkId = null;
for (Imp imp : request.getImp()) {
try {
final ExtImpSparteo extImp = parseExtImp(imp);
if (siteNetworkId == null && extImp.getNetworkId() != null) {
siteNetworkId = extImp.getNetworkId();
}
} catch (PreBidException e) {
errors.add(BidderError.badInput("ignoring imp id=%s, error processing ext: %s".formatted(imp.getId(), e.getMessage())));
}
modifiedImps.add(imp.toBuilder().ext(modifyImpExt(imp)).build());
}
if (modifiedImps.isEmpty()) {
return Result.withErrors(errors);
}
final BidRequest outgoingRequest = request.toBuilder()
.imp(modifiedImps)
.site(modifySite(request.getSite(), siteNetworkId, mapper))
.build();
final HttpRequest<BidRequest> call = BidderUtil.defaultRequest(outgoingRequest, endpointUrl, mapper);
return Result.of(Collections.singletonList(call), errors);
}
private ExtImpSparteo parseExtImp(Imp imp) {
try {
return mapper.mapper().convertValue(imp.getExt(), TYPE_REFERENCE).getBidder();
} catch (IllegalArgumentException e) {
throw new PreBidException("invalid imp.ext");
}
}
private static ObjectNode modifyImpExt(Imp imp) {
final ObjectNode modifiedImpExt = imp.getExt().deepCopy();
final JsonNode sparteoJsonNode = modifiedImpExt.get("sparteo");
final ObjectNode sparteoNode = sparteoJsonNode == null || !sparteoJsonNode.isObject()
? modifiedImpExt.putObject("sparteo")
: (ObjectNode) sparteoJsonNode;
final JsonNode paramsJsonNode = sparteoNode.get("params");
final ObjectNode paramsNode = paramsJsonNode == null || !paramsJsonNode.isObject()
? sparteoNode.putObject("params")
: (ObjectNode) paramsJsonNode;
final JsonNode bidderJsonNode = modifiedImpExt.remove("bidder");
if (bidderJsonNode != null && bidderJsonNode.isObject()) {
final Iterator<Map.Entry<String, JsonNode>> fields = bidderJsonNode.fields();
while (fields.hasNext()) {
Map.Entry<String, JsonNode> field = fields.next();
paramsNode.set(field.getKey(), field.getValue());
}
}
return modifiedImpExt;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, now we don't need ExtImpParamsSparteo
having separate DTOs was bad idea from my side according to the Go version because there is no strict list of fields we can potentially receive within the imp.ext
also ExtImpSparteo can be shrink to the following
@Value(staticConstructor = "of")
public class ExtImpSparteo {
@JsonProperty("networkId")
String networkId;
}
all the custom params will be copied to the outgoing DTO anyway
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please double-check in case I have missed something and sorry for confusion
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @AntoxaAntoxic ,
No problem, i admit that having no strict list of fields could misled.
Thank you to have spent time to refactor it. I have implemented the changes i just have changed the loop logic to include the
modifiedImps.add(imp.toBuilder().ext(modifyImpExt(imp)).build());
into the try block.
Please let me know if you see anything else.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the bidder itself looks good, some comments on the test class
src/main/java/org/prebid/server/bidder/sparteo/SparteoBidder.java
Outdated
Show resolved
Hide resolved
} | ||
} | ||
|
||
private BidderBid toBidderBid(Bid bid, String currency, List<BidderError> errors) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the method should be higher
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the rule behind ? I did an alphabetic order for private methods. Where should i put this method ?
src/test/java/org/prebid/server/bidder/sparteo/SparteoBidderTest.java
Outdated
Show resolved
Hide resolved
src/test/java/org/prebid/server/bidder/sparteo/SparteoBidderTest.java
Outdated
Show resolved
Hide resolved
src/test/java/org/prebid/server/bidder/sparteo/SparteoBidderTest.java
Outdated
Show resolved
Hide resolved
final HttpRequest<BidRequest> httpRequest = result.getValue().get(0); | ||
assertThat(httpRequest.getMethod()) | ||
.isEqualTo(HttpMethod.POST); | ||
assertThat(httpRequest.getUri()) | ||
.isEqualTo(ENDPOINT_URL); | ||
|
||
final BidRequest outgoingRequest = httpRequest.getPayload(); | ||
assertThat(outgoingRequest.getImp()) | ||
.hasSize(1); | ||
final ObjectNode modifiedImpExt = outgoingRequest.getImp().get(0).getExt(); | ||
assertThat(modifiedImpExt | ||
.get("sparteo") | ||
.get("params") | ||
.get("networkId") | ||
.asText()) | ||
.isEqualTo("testNetworkId"); | ||
assertThat(modifiedImpExt | ||
.get("sparteo") | ||
.get("params") | ||
.get("customParam") | ||
.asText()) | ||
.isEqualTo("customValue"); | ||
assertThat(modifiedImpExt.has("bidder")) | ||
.isFalse(); | ||
|
||
final ExtPublisher publisherExt = (ExtPublisher) outgoingRequest.getSite().getPublisher().getExt(); | ||
assertThat(publisherExt | ||
.getProperties() | ||
.get("params") | ||
.get("networkId") | ||
.asText()) | ||
.isEqualTo("testNetworkId"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please utilize assertj extracting methods whenever it's possible
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated but i'm not 100% i did it the right way, do not hesitate to tell me if it is not what you expected
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's especially handy while working with lists of objects instead of comparing one by one with the duplicated code
src/test/java/org/prebid/server/bidder/sparteo/SparteoBidderTest.java
Outdated
Show resolved
Hide resolved
src/test/java/org/prebid/server/bidder/sparteo/SparteoBidderTest.java
Outdated
Show resolved
Hide resolved
src/test/java/org/prebid/server/bidder/sparteo/SparteoBidderTest.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, looks good. Only minor issues are left. Thank you!
src/test/java/org/prebid/server/bidder/sparteo/SparteoBidderTest.java
Outdated
Show resolved
Hide resolved
src/test/java/org/prebid/server/bidder/sparteo/SparteoBidderTest.java
Outdated
Show resolved
Hide resolved
53c2d04
to
5f5206f
Compare
🔧 Type of changes
✨ What's the context?
We would like to allow our partners to be able to include us in s2s bidding.
The Go PR: prebid/prebid-server#4275
🧠 Rationale behind the change
The adapter logic is the same as the one we have implemented for the GO version
🔎 New Bid Adapter Checklist
🧪 Test plan
How do you know the changes are safe to ship to production?
We have implemented the unit and integration test.
We have run several manual "real" tests.
🏎 Quality check