0

I'm getting an error where the entity class's variable is not found while the variable is clearly there and the entity class is found

@RestController
public class LanguageController {
    

    @Autowired
    private LanguageService service;
    
    @RequestMapping("/language")
    public List<Language> allLanguages() {
        return service.getAllLanguages();
        }
    
    @RequestMapping("/language/{id}")
    public Optional<Language> allLanguagesById(@PathVariable String id) {
        return service.getLanguagesById(id);    
    }
    


    @RequestMapping(value = "/language", method = RequestMethod.POST)
    public void addTopic(@RequestBody Language topic) { 
        service.addLanguage(topic);
    }
    
    // addLanguage used to save/add depending if obj already exists
    // Will need more variable in obj for it to truly update
    @RequestMapping(value = "/language/{id}", method = RequestMethod.PUT)
    public void updateTopic(@RequestBody Language lang) {
        service.addLanguage(lang);
    }
    

    @RequestMapping(value = "/language/{id}", method = RequestMethod.DELETE)
    public void deleteTopics(@PathVariable String id) {
        service.deleteLanguage(id);
    }
    
    
}

entity class

package com.Alex.language;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;

import com.Alex.language.Language;

// JPA to create columns according it
// Act as table labels
@Entity
public class Topics {
    
    // Mark primary key
    @Id
    private String id;
    private String name;
    private String description;
    
    // Many topics to one language
    @ManyToOne
    private Language lang;
    
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    
    public Topics() {
        
    }
    public Topics(String id, String name, String description, String langId) {
        super();
        this.id = id;
        this.name = name;
        this.description = description;
        this.lang = new Language(langId);
    }
    public Language getLang() {
        return lang;
    }

    public void setLang(Language lang) {
        this.lang = lang;
    }

}

  package com.Alex.language;

import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Language { 

    @Id
    private String langId;


    
    public String getLangId() {
        return langId;
    }

    public void setLangId(String langId) {
        this.langId = langId;
    }

    public Language(String langId) {
        super();
        this.langId = langId;
    }

public Language() {
        
    }
}

Controller class

package com.Alex.language;

import java.util.List;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.Alex.language.Language;

// Used to create RESTful web services
@RestController
public class TopicsController {
    
    // As the database is embedded, will have to add data before able to see in Postman
    @Autowired
    private TopicService service;
    
    @RequestMapping("/language/{id}/topics")
    public List<Topics> getAllTopics(@PathVariable String id) {
        return service.getAllTopicsByLanguageId(id);
        }
        
    // @PathVariable get variable from @RequestMapping {id}
    @RequestMapping("/language/{langId}/topics/{id}")
    public Optional<Topics> getSpecifiedTopic(@PathVariable String id) {
        return service.getTopic(id);    
    }
    
    
    // @RequestBody to convert JSON object to Java object to be used
    @RequestMapping(value = "/language/{langId}/topics", method = RequestMethod.POST)
    public void addTopic(@RequestBody Topics topic, @PathVariable String langId) {  
        topic.setLang(new Language(langId));
        service.addTopic(topic);
    }
    
    @RequestMapping(value = "/language/{langId}/topics/{id}", method = RequestMethod.PUT)
    public void updateTopic(@PathVariable String langId, @RequestBody Topics topic) {
        topic.setLang(new Language(langId));
        service.updateTopic(topic);
    }
    
    @RequestMapping(value = "/language/{langId}/topics/{id}", method = RequestMethod.DELETE)
    public void deleteTopics(@PathVariable String id) {
        service.deleteTopic(id);
    }
    
    
}

So, I get the following error message when I type in the url something like this in Postman. localhost:8080/language/java/topics ( POST )

message=Unable to find com.Alex.language.Language with id langId; nested exception is javax.persistence.EntityNotFoundException: Unable to find com.Alex.language.Language with id langId, path=/language/java/topics}]

EDIT: Remove " " between langId which makes a literal String. Silly me, this is one of the mistakes I make most commonly :/

Solving that, I'm getting " Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'langId' in value "/language/${langId}/topics/{id}". I believe there is some configuration problem in main or so.

Fenzox
  • 334
  • 4
  • 20
  • The exception is a persistence layer exception, it does not say the variable/member is not found but it says it was not able to retrieve the details from the persistent storage based on the langId that was supplied in this case 'java'. What is the persistent storage in this case? Where is the mapping between the entity (table/collection) in the storage and this entity class? Is there an entry for 'java' in persistent storage? Ref. https://docs.oracle.com/javaee/6/api/javax/persistence/EntityNotFoundException.html – Vivek Jul 05 '20 at 21:28
  • Thank you for the clarification. In that case, shouldn't @PathVariable grab the langId and allow the retrieval? – Fenzox Jul 05 '20 at 21:32
  • Here is what is happening Request -> localhost:8080/language/java/topics Spring Boot -> ah this matches @RequestMapping("/language/{id}/topics") Wait a minute there is a variable in the request {id}, lets determine value of {id} id = java whats next service.getAllTopicsByLanguag('java') So it is indeed determining the value of id as java but internally when it tries to retrieve/load the object where langId = java from the persistent storage it fails and thus the exception – Vivek Jul 05 '20 at 21:35
  • Right, it's going to go to the database next and locate that particular entry? And according to the method, populate whatever there is under "java". I'm using CrudeRepository from a tutorial on Youtube, are you suggesting there is a problem with the implementation of CrudeRepository? I was able to store the objects perfectly in another controller where it messes with language only – Fenzox Jul 05 '20 at 21:38
  • Exactly, so these 2 questions are what would bring the problem to its resolution - Where is the mapping between the entity (table/collection) in the storage and this entity class? Is there an entry for 'java' in persistent storage? – Vivek Jul 05 '20 at 21:41
  • https://www.concretepage.com/java/jpa/jpa-entity-example This example might help – Vivek Jul 05 '20 at 21:43
  • Under the class Topics I have @ManyToOne private Language lang; which connects the both of them – Fenzox Jul 05 '20 at 21:44
  • The focus was on following when we say mapping between an entity in storage and the class `@Entity **@Table(name="farmer")** public class Farmer { @Id **@Column(name="id")** private int id;` – Vivek Jul 05 '20 at 21:51
  • I half-solved the problem by removing the "" between langId which makes it literally a String – Fenzox Jul 05 '20 at 21:53
  • ok, had missed that part in the code. second part is most likely the mapping. – Vivek Jul 05 '20 at 21:54
  • Yeah that's always a tricky one. Are the table annotations for MySQL table afterwards? Is it always necessary? – Fenzox Jul 05 '20 at 21:56
  • can you post the mapping the post. – Vivek Jul 05 '20 at 22:00
  • Added to my initial post – Fenzox Jul 05 '20 at 22:08
  • So your second method has only one parameter but 2 placeholders {langId} & {id} but only @PathVariable String id – Vivek Jul 05 '20 at 22:12
  • Referring to this method `// @PathVariable get variable from @RequestMapping {id} @RequestMapping("/language/{langId}/topics/{id}") public Optional getSpecifiedTopic(@PathVariable String id) { return service.getTopic(id); }` – Vivek Jul 05 '20 at 22:14
  • I did that thinking it shouldn't be a problem. Or do I need to use langId to locate the object? – Fenzox Jul 05 '20 at 22:15
  • yes you would need that at least mapped as `@PathVariable`, not sure how it gets used in the logic – Vivek Jul 05 '20 at 22:22
  • , message=ids for this class must be manually assigned before calling save(): com.Alex.language.Language; nested exception is org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): com.Alex.language.Language, path=/language}]. Thanks for information previously. I'm trying to assign the value manually in application URL but it pops this error. Does it mean I have to generatedValue annotation? – Fenzox Jul 05 '20 at 22:26
  • https://www.objectdb.com/java/jpa/entity/generated – Vivek Jul 05 '20 at 22:28
  • There is some error using auto generation I think the type is a problem for String – Fenzox Jul 05 '20 at 22:30
  • Indeed and your id is not a random value which can be generated, its more of real value. – Vivek Jul 05 '20 at 22:34
  • I had no issues adding it previously before hitting the error in the question and solved it. Weird.. Seems like I'm going to figure this out before heading to bed – Fenzox Jul 05 '20 at 22:35
  • Change the getter and setter name for the Entity class language solves it. – Fenzox Jul 05 '20 at 22:40
  • Great, hope its working now end to end – Vivek Jul 05 '20 at 22:50

0 Answers0