Spring Data MongoDB No property get found for type at org.springframework.data.mapping.PropertyPath - mongodb

I am using Spring Data MongodB 1.4.2.Release version. For Spring Data MongoDB, I have created the custom repository interface and implementation in one location and create custom query function getUsersName(Users users).
However I am still getting below exception:
Caused by: org.springframework.data.mapping.PropertyReferenceException:
No property get found for type Users! at org.springframework.data.mapping.PropertyPath. (PropertyPath.java:75) at
org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:327) at
org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:359) at
org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:359) at
org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:307) at
org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:270) at
org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:241) at
org.springframework.data.repository.query.parser.Part.(Part.java:76) at
org.springframework.data.repository.query.parser.PartTree$OrPart.(PartTree.java:201) at
org.springframework.data.repository.query.parser.PartTree$Predicate.buildTree(PartTree.java:291) at
org.springframework.data.repository.query.parser.PartTree$Predicate.(PartTree.java:271) at
org.springframework.data.repository.query.parser.PartTree.(PartTree.java:80) at
org.springframework.data.mongodb.repository.query.PartTreeMongoQuery.(PartTreeMongoQuery.java:47)
Below is my Spring Data MongoDB structure:
/* Users Domain Object */
#Document(collection = "users")
public class Users {
#Id
private ObjectId id;
#Field ("last_name")
private String last_name;
#Field ("first_name")
private String first_name;
public String getLast_name() {
return last_name;
}
public void setLast_name(String last_name) {
this.last_name = last_name;
}
public String getFirst_name() {
return first_name;
}
public void setFirst_name(String first_name) {
this.first_name = first_name;
}
}
/* UsersRepository.java main interface */
#Repository
public interface UsersRepository extends MongoRepository<Users,String>, UsersRepositoryCustom {
List findUsersById(String id);
}
/* UsersRepositoryCustom.java custom interface */
#Repository
public interface UsersRepositoryCustom {
List<Users> getUsersName(Users users);
}
/* UsersRepositoryImpl.java custom interface implementation */
#Component
public class UsersRepositoryImpl implements UsersRepositoryCustom {
#Autowired
MongoOperations mongoOperations;
#Override
public List<Users> getUsersName(Users users) {
return mongoOperations.find(
Query.query(Criteria.where("first_name").is(users.getFirst_name()).and("last_name").is(users.getLast_name())), Users.class);
}
/* Mongo Test function inside Spring JUnit Test class calling custom function with main UsersRepository interface */
#Autowired
private UsersRepository usersRepository;
#Test
public void getUsersName() {
Users users = new Users();
users.setFirst_name("James");`enter code here`
users.setLast_name("Oliver");
List<Users> usersDetails = usersRepository.getUsersName(users);
System.out.println("users List" + usersDetails.size());
Assert.assertTrue(usersDetails.size() > 0);
}

The query method declaration in your repository interface is invalid. As clearly stated in the reference documentation, query methods need to start with get…By, read_By, find…By or query…by.

With custom repositories, there shouldn't be a need for method naming conventions as Oliver stated. I have mine working with a method named updateMessageCount
Having said that, I can't see the problem with the code provided here.
I resolved this issue with the help of this post here, where I wasn't naming my Impl class correctly :
No property found for type error when try to create custom repository with Spring Data JPA

Related

Query for multiple values of the same property with queryDSL and Spring Data JPA

Is there a way to query for multiple values of the same property with Spring DataREST JPA and querydsl? I am not sure what the format of the query URL should be and if I need extra customization in my bindings. I couldn't find anything in documentation. If I have a "student" table in my database with a "major" column with corresponding Student entity I would assume that querying for all students which have "math" and "science" majors would look like http://localhost:8080/students?major=math&major=science. However in this query only the first part is being taken and major=science is ignored
Below example customizes Querydsl web support to perform collection in operation. URI /students?major=sword&major=magic searches for students with major in ["sword", "magic"].
Entity and repository
public class Student {
private Long id;
private String name;
private String major;
}
public interface StudentRepos extends PagingAndSortingRepository<Student, Long>,
QuerydslPredicateExecutor<Student>,
QuerydslBinderCustomizer<QStudent> {
#Override
default void customize(QuerydslBindings bindings, QStudent root) {
bindings.bind(root.major)
.all((path, value) -> Optional.of(path.in(value)));
}
}
Test data
new Student("Arthur", "sword");
new Student("Merlin", "magic");
new Student("Lancelot", "lance");
Controller
#RestController
#RequestMapping("/students")
#RequiredArgsConstructor
public class StudentController {
private final StudentRepos studentRepos;
#GetMapping
ResponseEntity<List<Student>> getAll(Predicate predicate) {
Iterable<Student> students = studentRepos.findAll(predicate);
return ResponseEntity.ok(StreamSupport.stream(students.spliterator(), false)
.collect(Collectors.toList()));
}
}
Test case
#Test
#SneakyThrows
public void queryAll() {
mockMvc.perform(get("/students"))
.andExpect(status().isOk())
.andExpect(jsonPath("$").isArray())
.andExpect(jsonPath("$", hasSize(3)))
.andDo(print());
}
#Test
#SneakyThrows
void querySingleValue() {
mockMvc.perform(get("/students?major=sword"))
.andExpect(status().isOk())
.andExpect(jsonPath("$").isArray())
.andExpect(jsonPath("$", hasSize(1)))
.andExpect(jsonPath("$[0].name").value("Arthur"))
.andExpect(jsonPath("$[0].major").value("sword"))
.andDo(print());
}
#Test
#SneakyThrows
void queryMultiValue() {
mockMvc.perform(get("/students?major=sword&major=magic"))
.andExpect(status().isOk())
.andExpect(jsonPath("$").isArray())
.andExpect(jsonPath("$", hasSize(2)))
.andExpect(jsonPath("$[0].name").value("Arthur"))
.andExpect(jsonPath("$[0].major").value("sword"))
.andExpect(jsonPath("$[1].name").value("Merlin"))
.andExpect(jsonPath("$[1].major").value("magic"))
.andDo(print());
}
The full Spring Boot application is in Github

Can I write my own Queries in a Spring boot web app?

I'm making my first springboot web app, and trying to display some information from a postgresql server. When trying to get some information out of the database, it returns an empty list. By what I can see in the console, it tries to query with the wrong parameters.
In my DB I have a table with three fields: "userId", "firstName", and "surName".
From what i can understand, Hibernate tries to query with the parameters "users0_.user_id", "users0_user_id", "users0_.sur_name".
To fix this i want to write my own queries or fix the current one. How do I do this?
As you can see I have checked the results of the query with some System.Out.print statements.
The first one returned a list.size() of 0,
and the second one returned a value of null.
Console displaying what I think is the query info
This is the function in my UserController class used to display the users' info.
#RequestMapping("/users")
public String getUsers(Model model) {
List <users>users = (List<users>) userServ.listAll();
System.out.print("THE SIZE WITH STRING CONCATINATION IS: " + users.size());
model.addAttribute("users", users);
System.out.print("THE NAME OF USER WITH INDEX =2 IS: " + userServ.getById(2).getFirstName());
return "showUsers";
}
The entity/domain-class for a user:
#Entity
#Table(name="users")
public class users implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long userId;
private String firstName;
private String surName;
private long getId() { return userId; }
public void setId(long id) {this.userId = id;}
public String getFirstName() { return firstName; }
public String getSurName() { return surName; }
public void setSurname(String surName) {this.surName = surName; }
}
This is the interface of the repository used to retrieve users from the DB:
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.repository.CrudRepository;
import com.svein.models.users;
public interface UserRepository extends CrudRepository<users, Long> {
}
This is the service class for the users:
#Service
public class UserServiceImp implements userService{
#Autowired
private UserRepository userRepo;
#Override
public List<users> listAll() {
List<users> users = new ArrayList<>();
userRepo.findAll().forEach(users::add);
return users;
}
#Override
public users getById(long id) {
return userRepo.findById(id).orElseGet(users::new);
}
#Override
public users saveOrUpdate(users user) {
userRepo.save(user);
return null;
}
#Override
public void delete(Long id) {
userRepo.deleteById(id);
}
}
I was hoping to adjust or replace the current query, but maybe there is something alse wrong with the code. As I said, I'm quite new to this, but thought it was weird that i had not written a single line of SQL, and in a different project THAT showed signs of retrieving the right information(from a different DB). How does the class know what to query for?
You need to add an #Query annotation on top of query function you want to write in your UserRepository class.
For e.g
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.repository.CrudRepository;
import com.svein.models.users;
public interface UserRepository extends CrudRepository<users, Long> {
#Query("Select * from users")
List<users> findAllUsers();
}
Alternatively in your UserServiceImpl, userRepo.findAll() should work.You do not need to loop through each user and return it to list. You should simply return userRepo.findAll().
Following url would give you more idea about how to write your own query.
https://www.baeldung.com/spring-data-jpa-query

Rest API with Spring Data MongoDB - Repository method not working

I am reading and learning Spring Boot data with MongoDB. I have about 10 records in my database in the following format:
{
"_id" : ObjectId("5910c7fed6df5322243c36cd"),
name: "car"
}
When I open the url:
http://localhost:8090/items
I get an exhaustive list of all items. However, I want to use the methods of MongoRepository such as findById, count etc. When I use them as such:
http://localhost:8090/items/count
http://localhost:8090/items/findById/5910c7fed6df5322243c36cd
http://localhost:8090/items/findById?id=5910c7fed6df5322243c36cd
I get a 404.
My setup is as so:
#SpringBootApplication
public class Application {
public static void main(String[] args) throws IOException {
SpringApplication.run(Application.class, args);
}
}
#Document
public class Item implements Serializable {
private static final long serialVersionUID = -4343106526681673638L;
#Id
private String id;
private String name;
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;
}
}
#RepositoryRestResource(collectionResourceRel = "item", path = "items")
public interface ItemRepository<T, ID extends Serializable> extends MongoRepository<Item, String>, ItemRepositoryCustom {
}
What am I doing wrong? Do I need to implement the methods as defined by MongoRepository or will they be automatically implemented? I am lost and have been trying to figure this out for so long. I do not have any methods in my controller, its empty.
You have to declare the findById method in order for it to be exposed.
Item findById(String id);
Item findByName(String name);
Note that you don't need to implement the methods. SpringBoot will analyse the method name and provide the proper implementation
I had same issue,
After removing #Configuration,#ComponentScan everything worked fine.

IllegalArgumentException: NamedQuery using Spring JPA

I am using namedquery for rest api using Spring JPA. The named query is implemented in my entity class:
#Entity
#Table(name="SPECIMEN_TB")
#NamedQueries({
#NamedQuery(name="SpecimenTb.findBySpecimenNo", query="select s from SpecimenTb s where s.specimenNo = :specimenNo"),
})
public class SpecimenTb implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SPECIMEN_TB_ROWID_GENERATOR")
#Column(name="ROW_ID")
private long rowId;
#Column(name="SPECIMEN_NO", unique = true)
private String specimenNo;
My controller looks like this:
#RestController
public class RistoreController {
#Autowired
private RistoreService ristoreService;
#RequestMapping(
value = "/ristore/foundation/{specno}",
method = RequestMethod.GET,
produces = "application/json")
public ResponseEntity<SpecimenTb> getFmSpecimen(#PathVariable("specno") String specno) {
List<SpecimenTb> specimens = ristoreService.findBySpecimenNo(specno);
if (specimens == null) {
return new ResponseEntity<SpecimenTb>(HttpStatus.NOT_FOUND);
}
return new ResponseEntity<SpecimenTb>(specimens.get(0), HttpStatus.OK);
}
I have a service bean which calls JPA repository findBySpecimenNo method.
#Service
public class RistoreServiceBean implements RistoreService {
#Autowired
private SpecimenRepository specimenRepository;
#Override
public List<SpecimenTb> findAll() {
List<SpecimenTb> specimens = specimenRepository.findAll();
return specimens;
}
#Override
public List<SpecimenTb> findBySpecimenNo(String specimenNo) {
List<SpecimenTb> specimens = specimenRepository.findBySpecimenNo(specimenNo);
return specimens;
}
When I start the Spring Boot Application and type in the url "http://localhost:8080/ristore/foundation/SKM1", I got the following error:
java.lang.IllegalArgumentException: Parameter with that position [1] did not exist
What did I do wrong?
Looks like you can't use a named parameter with the #NamedQuery based on the docs I read. Have you tried with ?1 instead?
Reason that named parameter doesn't work is that you also have to add the annotation on the method parameter so Spring knows which parameter matches to what placeholder in the query.

No mapping available for role reference with sessionContext.isCallerInRole()

I have a method that can be called if the person has a specific role and they are associated with a particular group in JIRA. Since the groups in JIRA are dynamic, I can't have a role per JIRA group.
#DeclareRoles({
FileServerRoles.FILE_ADDER,
FileServerRoles.FILE_ADDER_ALL,
FileServerRoles.FILE_VIEWER,
FileServerRoles.FILE_VIEWER_ALL})
public final class FileServerRoles {
/**
* A user that can add files to the system.
*/
public static final String FILE_ADDER = "file-adder";
/**
* A user that can add any files to the system.
*/
public static final String FILE_ADDER_ALL = "file-adder-all";
/**
* A user that can view files in the system.
*/
public static final String FILE_VIEWER = "file-viewer";
/**
* A user that can view all files in the system.
*/
public static final String FILE_VIEWER_ALL = "file-viewer-all";
}
I am declaring all of the roles using #DeclareRoles.
#Decorator
public class FileServerServiceProjectAuthorizationDecorator implements FileServerService {
private static Logger LOGGER = LoggerFactory.getLogger(FileServerServiceProjectAuthorizationDecorator.class);
#Inject
#Delegate
#Any
FileServerService delagate;
#Inject
#CurrentUser
Set<JiraProjectReference> currentUserProjectReferences;
#Resource
SessionContext sessionContext;
void verifyProjectKey(final String projectKey) {
for (final JiraProjectReference projectReference : currentUserProjectReferences) {
if (projectReference.getKey().equalsIgnoreCase(projectKey)) {
return;
}
}
throw new IllegalArgumentException("user not in the project");
}
#RolesAllowed({FileServerRoles.FILE_ADDER, FileServerRoles.FILE_ADDER_ALL})
#Override
public FileAddStatus addFileToRepository(final String projectKey, final String issueKey, final String fileName, final String mimeType, final File file) {
if (!sessionContext.isCallerInRole(FileServerRoles.FILE_ADDER_ALL)) {
verifyProjectKey(projectKey);
}
return delagate.addFileToRepository(projectKey, issueKey, fileName, mimeType, file);
}
#RolesAllowed({FileServerRoles.FILE_VIEWER, FileServerRoles.FILE_VIEWER_ALL})
#Override
public FileDescriptor retrieveFileFromRepository(final String projectKey, final String issueKey, final UUID uuid, final String fileName) {
if (!sessionContext.isCallerInRole(FileServerRoles.FILE_VIEWER_ALL)) {
verifyProjectKey(projectKey);
}
return delagate.retrieveFileFromRepository(projectKey, issueKey, uuid, fileName);
}
}
!sessionContext.isCallerInRole(FileServerRoles.FILE_VIEWER_ALL) always throws IllegalStateException:
Caused by: java.lang.IllegalStateException: No mapping available for role reference file-viewer-all
at com.sun.ejb.containers.EJBContextImpl.isCallerInRole(EJBContextImpl.java:458)
at edu.wvu.esd.swordfish.web.service.FileServerServiceProjectAuthorizationDecorator.retrieveFileFromRepository(FileServerServiceProjectAuthorizationDecorator.java:59)
... 89 more
I have had no problem with any of the roles when that are referenced in #RolesAllowed. I have also tried moving the roles declaration into web.xml. There aren't many references to the error on google.
Has anyone seen this? What was your solution?
I was receiving the same "No mapping available for role reference" error when calling the isCallerInRole(roleName) method within an EJB in GlassFish 3.1. What fixed it for me was adding the appropriate #DeclareRoles annotation to my EJB. If the role name passed to isCallerInRole is not in #DeclareRoles, an IllegalStateException gets thrown. I'm not sure how security works within a decorator but #DeclareRoles was the key for me.
Here is a simple example:
#Stateless
#LocalBean
#DeclareRoles({"user", "admin"})
public class ExampleEJB {
#Resource
private SessionContext sessionContext;
public boolean isUserInRole(String roleName) {
return sessionContext.isCallerInRole(roleName);
}
}