Last active
November 8, 2022 05:28
-
-
Save Kshitij-Dhakal/14401df140f23704c09d48c6ca9ac425 to your computer and use it in GitHub Desktop.
Field Mask Demo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
plugins { | |
id 'java' | |
id "com.google.protobuf" version "0.9.1" | |
} | |
group 'org.example' | |
version '1.0-SNAPSHOT' | |
repositories { | |
mavenCentral() | |
} | |
dependencies { | |
implementation 'com.google.protobuf:protobuf-java:3.21.9' | |
implementation 'io.grpc:grpc-all:1.50.2' | |
runtimeOnly 'com.google.protobuf:protobuf-java-util:3.21.9' | |
} | |
test { | |
useJUnitPlatform() | |
} | |
protobuf { | |
protoc { artifact = "com.google.protobuf:protoc:3.13.0" } | |
plugins { | |
grpc { artifact = "io.grpc:protoc-gen-grpc-java:1.31.1" } | |
} | |
generateProtoTasks { | |
all()*.plugins { grpc {} } | |
} | |
} | |
sourceSets { | |
main { | |
proto { | |
srcDirs 'src/main/proto' | |
} | |
java { | |
srcDirs 'build/generated/source/proto/main/grpc' | |
srcDirs 'build/generated/source/proto/main/java' | |
} | |
} | |
} | |
tasks.withType(Copy) { | |
filesMatching("**/*.proto") { | |
duplicatesStrategy = DuplicatesStrategy.INCLUDE | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.example; | |
import com.google.protobuf.FieldMask; | |
import com.google.protobuf.InvalidProtocolBufferException; | |
import com.google.protobuf.util.FieldMaskUtil; | |
import com.google.protobuf.util.JsonFormat; | |
import org.example.pb.Address; | |
import org.example.pb.UpdateUserRequest; | |
import org.example.pb.User; | |
import org.slf4j.Logger; | |
import org.slf4j.LoggerFactory; | |
import java.util.UUID; | |
public class FieldMaskExample { | |
private static final Logger log = LoggerFactory.getLogger(FieldMaskExample.class); | |
public static void main(String[] args) throws InvalidProtocolBufferException { | |
var entity = User.newBuilder() // fetched from db | |
.setId(UUID.randomUUID().toString()) | |
.setName("Aubrey Queen") | |
.setPicture("https://example.org/") | |
.setEmail("[email protected]") | |
.setPassword("password") | |
.setAddress(Address.newBuilder() | |
.setStreet("Street-1") | |
.setCity("City-1") | |
.setState("State-1") | |
.setZipCode("11111") | |
.build()) | |
.build(); | |
fetchMaskExample(entity); | |
updateMaskExample(entity); | |
} | |
private static void fetchMaskExample(User entity) throws InvalidProtocolBufferException { | |
// return only those fields that client requires | |
var mask = FieldMask.newBuilder() | |
.addPaths("name") | |
.addPaths("email") | |
.addPaths("password") | |
.addPaths("address.street") | |
.build(); | |
log.info("{}", JsonFormat.printer().print(FieldMaskUtil.trim(mask, entity))); | |
// expected : | |
// { | |
// "name": "Aubrey Queen", | |
// "email": "[email protected]", | |
// "password": "password", | |
// "address": { | |
// "street": "Street-1" | |
// } | |
// } | |
// | |
// Only masked fields are returned and other fields are omitted | |
} | |
private static void updateMaskExample(User entity) throws InvalidProtocolBufferException { | |
// update exactly only those fields which are specified in field mask | |
// this way we don't need to make multiple patch api for every fields like | |
// @PATCH("/user/:user-id/name") | |
// @PATCH("/user/:user-id/picture") | |
// @PATCH("/user/:user-id/email") | |
// @PATCH("/user/:user-id/password") | |
// | |
// Instead only one PUT API will do the job where we will send update request and mask | |
// @PUT("/user/:user-id") | |
var mask = FieldMask.newBuilder() | |
.addPaths("name") | |
.addPaths("password") | |
.build(); | |
// var mask = FieldMaskUtil.fromFieldNumbers(User.class, 2, 5); we can use this also to get same result | |
var updateUserRequest = UpdateUserRequest.newBuilder() | |
.setUser(User.newBuilder() | |
.setName("Sheryl Parsons") | |
.setPassword("p@55w0rd") | |
.build()) | |
.setUpdateMask(mask) | |
.build(); | |
var destination = entity.toBuilder(); | |
FieldMaskUtil.merge(updateUserRequest.getUpdateMask(), // mask to apply | |
updateUserRequest.getUser(), // source (update request) | |
destination); // destination (entity fetched from db) | |
log.info("{}", JsonFormat.printer().print(destination.build())); | |
// expected : | |
// { | |
// "id": "db304f29-fc17-4adc-93a9-fcbf4735192b", | |
// "name": "Sheryl Parsons", | |
// "picture": "https://example.org/", | |
// "email": "[email protected]", | |
// "password": "p@55w0rd", | |
// "address": { | |
// "street": "Street-1", | |
// "city": "City-1", | |
// "state": "State-1", | |
// "zipCode": "11111" | |
// } | |
// } | |
// | |
// only name and password is updated | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
syntax = "proto3"; | |
package org.example; | |
option go_package = "pb"; | |
option java_package = "org.example.pb"; | |
option java_multiple_files = true; | |
import "google/protobuf/field_mask.proto"; | |
message Address { | |
string street = 1; | |
string city = 2; | |
string state = 3; | |
string zipCode = 4; | |
} | |
message User { | |
string id = 1; | |
string name = 2; | |
string picture = 3; | |
string email = 4; | |
string password = 5; | |
Address address = 6; | |
} | |
message UpdateUserRequest { | |
// The User resource which replaces the resource on the server. | |
User User = 1; | |
// The update mask applies to the resource. For the `FieldMask` definition, | |
// see https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#fieldmask | |
google.protobuf.FieldMask update_mask = 2; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Demo API made in spring boot