Skip to content
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

[BUG] Etag Value return null if etag attribute is annotated with @Version and @JsonProperty("_etag") in container class. || Spring Boot || ReactiveCosmosRepository #40038

Open
3 tasks done
SanjayDasTezpur opened this issue May 5, 2024 · 3 comments
Assignees
Labels
Azure.Spring - Cosmos azure-spring All azure-spring related issues azure-spring-cosmos Spring cosmos related issues. Client This issue points to a problem in the data-plane of the library. customer-reported Issues that are reported by GitHub users external to the Azure organization. needs-team-attention This issue needs attention from Azure service team or SDK team question The issue doesn't require a change to the product in order to be resolved. Most issues start as that

Comments

@SanjayDasTezpur
Copy link

Describe the bug
Etag Value return null if etag attribute is annotated with @Version and @JsonProperty("_etag") in container class. || Spring Boot || ReactiveCosmosRepository

Exception or Stack Trace
No Exception , But Etag becomes null. which create problem (412 precondition exception) in further update operation , as etag is null.

To Reproduce

  1. Create a Entity Class [say Person, annotated with @Container].
  2. add a attribute [member variable] with name etag, and annotate this with @Version @JsonProperty("_etag") , @Version is used to enable concurrency . [If invalid etag is passed while updating it should throw an exception, i.e. pre condition exception]
  3. Now create a Repository interface of Spring Boot , either ReactiveCosmosRepository<Person, String> or CosmosRepository<Person, String>.
  4. Now from any Service or Controller Class try to execute repository.save(person) , record will be saved in database, but the returned saved person object will have etag as null.
  • Now, If I remove just @Version annotation and keep @JsonProperty("_etag") , then I get the correct etag , but I have to compromise concurrency, which is not permissible in our system.
  • Second, If I remove just @JsonProperty("_etag") annotation and keep @Version, then concurreny control works fine, and also recieve correct etag. But the problem here is , we use stored procedure to update the record , to achieve optimistic transaction, so in the database, in the document a new attribute gets created with name etag along with _etag. etag holds the last etag value, where as _etag has the latest value.

Code Snippet
Person.Java

@Data
@Container(containerName = "person")
public class Person {
    @Id
    private String id;

    @PartitionKey
    private String lastName;

    private String firstName;

    private String email;

    @Version
    @JsonProperty("_etag")
    private String etag;

    @JsonProperty("_self")
    private String self;
}

PersonRepository.java

@Repository
public interface PersonRepository extends ReactiveCosmosRepository<Person, String> {
}

PersonService.java

@Service
@RequiredArgsConstructor
public class PersonService {

    private final PersonRepository personRepository;
    private final PersonUpdator personUpdator;

    public Mono<Person> save(Person person) {
        return personRepository.save(person);
    }

    public Mono<Person> get(String id) {
        return personRepository.findById(id);
    }

    public Person update(Person person) {
        personUpdator.executeStoredProcForUpdatePerson(person, person.getLastName());
    }
}

PersonController.java


@RestController
@RequiredArgsConstructor
public class FlexiHierarchyController {

    private final PersonService personService;

    @PostMapping("/person")
    public Mono<Person> personSave(@RequestBody Person person){
       return personService.save(person);
    }
    @GetMapping("/person")
    public Mono<Person> personGet(@RequestParam String id){
        return personService.get(id);
    }

    @PutMapping("/person")
    public Person personUpdate(@RequestBody Person person){
        return personService.update(person);
    }

}

updatePerson.js -> Cosmos DB Stored Proce

function updatePerson(personToUpdate){
    var context = getContext();
    var collection = getContext().getCollection();
    var doc = personToUpdate;

    // Some other tasks. 1.2.3....
    //replace ENTITY patch document
    var isAccepted1 = collection.replaceDocument(doc._self, doc, {etag: doc._etag},
                 function (err, documentCreated) {  
                  if (err) throw new Error('Error while updating Person document' + err.message);  
                    context.getResponse().setBody(documentCreated)  
            });  

    if(!isAccepted || !isAccepted1) throw new Error('Error while updating Person document');

}

PersonUpdator.java

public String executeStoredProcForUpdatePerson(Object personTobeUpdated, String partitionKey) throws Exception {
       
        CosmosStoredProcedureRequestOptions options = new CosmosStoredProcedureRequestOptions();
        options.setPartitionKey(new PartitionKey(partitionKey));
        List<Object> params = Arrays.asList(new ObjectMapper().writeValueAsString(personTobeUpdated));
        CosmosStoredProcedureResponse executeResponse = container.getScripts()
                .getStoredProcedure(updatePerson)
                .execute(params, options);
        return executeResponse.getResponseAsString();
    }

pom.xml

   <parent>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-parent</artifactId>
       <version>3.2.5</version>
       <relativePath/> <!-- lookup parent from repository -->
   </parent>
   <properties>
       <java.version>17</java.version>
       <spring-cloud-azure.version>5.11.0</spring-cloud-azure.version>
   </properties>
   <dependencyManagement>
       <dependencies>
           <dependency>
               <groupId>com.azure.spring</groupId>
               <artifactId>spring-cloud-azure-dependencies</artifactId>
               <version>${spring-cloud-azure.version}</version>
               <type>pom</type>
               <scope>import</scope>
           </dependency>
       </dependencies>
   </dependencyManagement>
   <dependencies>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-actuator</artifactId>
       </dependency>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-web</artifactId>
       </dependency>
       <dependency>
           <groupId>com.azure.spring</groupId>
           <artifactId>spring-cloud-azure-starter-data-cosmos</artifactId>
       </dependency>
   </dependencies>

Expected behavior
Two Things :

  1. Putting annotation @JsonProperty("_etag") on etag attribute should not make etag as null.
  2. If etag is annotated with @Version , then updating a record via stored proc should not create an etag attribute in the document .

Screenshots
image

Setup (please complete the following information):

  • OS: Mac Os
  • IDE: IntelliJ Ultimate
  • Library/Libraries: <spring-cloud-azure.version> 5.11.0 </spring-cloud-azure.version> , Please chcek above pom.xml to
  • Java version: 17
  • App Server/Environment: Sping Boot Default Tomcat
  • Frameworks: Spring Boot

Information Checklist
Kindly make sure that you have added all the following information above and checkoff the required fields otherwise we will treat the issuer as an incomplete report

  • Bug Description Added
  • Repro Steps Added
  • Setup information Added
@github-actions github-actions bot added azure-spring All azure-spring related issues Client This issue points to a problem in the data-plane of the library. customer-reported Issues that are reported by GitHub users external to the Azure organization. needs-team-attention This issue needs attention from Azure service team or SDK team question The issue doesn't require a change to the product in order to be resolved. Most issues start as that labels May 5, 2024
Copy link

github-actions bot commented May 5, 2024

Copy link

github-actions bot commented May 5, 2024

Thank you for your feedback. Tagging and routing to the team member best able to assist.

@kushagraThapar
Copy link
Member

@trande4884 can you please take a look at this issue, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Azure.Spring - Cosmos azure-spring All azure-spring related issues azure-spring-cosmos Spring cosmos related issues. Client This issue points to a problem in the data-plane of the library. customer-reported Issues that are reported by GitHub users external to the Azure organization. needs-team-attention This issue needs attention from Azure service team or SDK team question The issue doesn't require a change to the product in order to be resolved. Most issues start as that
Projects
Status: Todo
Development

No branches or pull requests

4 participants