Rest API with Spring Data MongoDB - Repository method not working - mongodb

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.

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

Spring Boot store data with WebSockets

I have a simple WebSocket set up and try to save data. Somehow the data gets not persisted. I don't get any error messages and the object gets returned correct to the client. If I try to store the object with a REST controller and a REST request it works.
Here are the dependencies of my build.gradle file:
dependencies {
compile 'org.springframework.boot:spring-boot-starter-web'
compile 'org.springframework.boot:spring-boot-starter-data-jpa'
compile 'org.springframework.boot:spring-boot-starter-websocket'
compile 'org.springframework:spring-messaging'
compile 'com.google.code.gson:gson:1.7.2'
compile 'org.postgresql:postgresql:9.4-1200-jdbc41'
compile 'commons-dbcp:commons-dbcp:1.4'
testCompile('org.springframework.boot:spring-boot-startet-test')
}
PersonController
#Controller
public class PersonController {
#Autowired
PersonRepository personRepository;
#MessageMapping("/test")
#SendTo("/response/test")
public Person test() throws Exception {
Person person = new Person();
person.setName("John Doe");
return personRepository.save(person);
}
}
Configuration for STOMP messaging
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
#Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/response");
config.setApplicationDestinationPrefixes("/app");
}
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/websocket")
.setAllowedOrigins("*")
.withSockJS();
}
Person entity
#Entity
public class Person {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String name;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return getName;
}
public void setName(String name) {
this.name = name;
}
}
Base Repository
#NoRepositoryBean
public interface BaseRepository<T, ID extends Serializable> extends Repository<T, ID> {
void delete(T deleted);
void delete(ID id);
Iterable<T> findAll();
T findOne(ID id);
T save(T persisted);
Iterable<T> save(Iterable<T> persited);
}
Person Repository
public interface PersonRepository extends
BaseRepository<Person, Serializable> {
}
Is there a problem in my code?
Is there an issue with caching? Do I have to force flushing?
Is storing data with WebSockets supported by SpringBoot?
Do you know any examples with storing data? I could only find basic examples without storing data.
The problem was in my persistence configuration. I changed the configuration from a Java implementation to the application.properties file. I think there was a problem with my transaction manager.
To be complete, here is my current application.properties file:
spring.datasource.url = jdbc:postgresql://localhost:5432/test
spring.datasource.username = test
spring.datasource.password = test
spring.datasource.testWhileIdle = true
spring.datasource.validationQuery = SELECT 1
spring.jpa.show-sql = true
spring.jpa.hibernate.ddl-auto = create
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect

Whether Replication Possible With Spring Data Couchbase?

HI i just want to know whether the XDCR replication is possible with spring data Couchbase. If possible how can i achieve that .please help .
My Code Sample
//configuration class
#Configuration
public class ApplicationConfig {
#Bean
public CouchbaseClient couchbaseClient() throws IOException {
return new CouchbaseClient(Arrays.asList(URI
.create("http://localhost:8091/pools")), "xxxw", "");
}
#Bean
public CouchbaseTemplate couchbaseTemplate() throws IOException {
return new CouchbaseTemplate(couchbaseClient());
}
}
#Document
public class Person {
#Field
String name;
#Id
String id;
public Person(final String personId, final String personname,
final int personIdAge, final JSONObject personData) {
this.id = personId;
this.name = personname;
this.age = personIdAge;
this.body = personData;
}
}
//main Test class
public class Test {
public static void main(String s[]) {
try {
ApplicationContext context = new AnnotationConfigApplicationContext(
ApplicationConfig.class);
CouchbaseTemplate template = context.getBean("couchbaseTemplate",
CouchbaseTemplate.class);
} catch (Exception e) {
e.printStackTrace();
}
}
How can i achieve repltcaion to elastic search index through spring data couchbase . with this sample classes ..??
Using elastic search in Couchbase is not dependent on what you client application looks like or whether or not it uses Spring. As long as you are storing data in Couchbase in JSON format things should work fine.
Setting up elastic search is more of an operations task than a development task. Take a look at the instructions at the link below and then run you application code as is. If you have configured everything properly then your data should end up in elastic search.
http://docs.couchbase.com/couchbase-elastic-search/

Spring 3 and JAXB

I have implemented a basic mvc app using Spring, i annotated my class as follows
I have added Spring oxm to my pom, but not added jaxb or json handlers.
My configuration is pretty much empty.
So my question is how is spring producing xml output when i call a GET in my controller and returning the following object in xml.
Where is it finding the xml marshaller, is it in the spring-oxm? is there default?
Is this the httpmessageconverters? i set my controller tot he following:
#RequestMapping(value= "/state", method = RequestMethod.GET, produces={MediaType.TEXT_XML_VALUE })
public ResponseEntity<GameState> getGameState(.. response,... request) {..}
my object :
#XmlRootElement(name = "door")
public class GameState {
private int id;
private String state;
public GameState() {
super();
}
public GameState(int id, String state) {
this.id = id;
this.state = state;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
Java 6 has JAXB built into the distro, you are specifying the container that ur looking by the
#XmlRootElement(name = "door")
If you will need more information on JAXB bundling here is the API documentation .