I am learning Spring Boot and I am trying to make a very simple app that fetches data from Mongo DB by using Dynamic Queries. I am using Intellij as my IDE.
FILE: application.properties (inside resource folder)
spring.mongo.host=127.0.0.1
spring.mongo.port=27017
spring.mongo.databaseName=spring
FILE: person.java
#Document (collection = "person")
public class Person {
#Id
String id;
int age;
String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
FILE: MyRepo.java
#Repository
public interface MyRepo extends PagingAndSortingRepository<Person, String> {
public List<Person> findAllByName(String name);
}
FILE: Config.java
#Configuration
#EnableMongoRepositories(basePackages = {"mongo.customQueries"})
public class Config {
}
FILE: Main.java
public class Main {
#Autowired
public static MyRepo myRepo;
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
MyRepo myRepo = context.getBean(MyRepo.class);
System.out.println(myRepo.findAllByName("Avishek"));
}
}
When I run the project, I get an error
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [mongo.customQueries.MyRepo] is defined
What is it that I am missing here? Why is my MyRepo bean not created as most of the examples in net are doing so.
The problem is you want to annotation the MyRepo in the Main class, please remove it as below:
public class Main {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
MyRepo myRepo = context.getBean(MyRepo.class);
System.out.println(myRepo.findAllByName("Avishek"));
}
}
If someone could just give me a simple example to run Dynamic Queries
in Spring boot with mongo. Some examples similar to that of above. Or
how can I make the above example correct.
You can see working example here. And find explanations here.
Related
I have recently done an experiment to see how we can use Lombok to reduce boilerplate in our code.
The issue:
When creating a simple data class with a builder through Lombok annotations, in IntelliJ IDEA, I cannot right click a field, then select Analyze Data Flow to Here.
This is using the latest IntelliJ Lombok Plugin. IntelliJ Ultimate 2019.2.3.
Is there any fix for this or is it simply not supported?
Example 1 - no lombok:
public class Person {
private String name;
private int age;
private Person() {
}
public Person(Builder builder) {
name = builder.name;
age = builder.age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public static class Builder {
private String name;
private int age;
public Builder name(String val) {
this.name = val;
return this;
}
public Builder age(int val) {
this.age = val;
return this;
}
public Person build() {
return new Person(this);
}
}
}
public class Main {
public static void main(String[] args) {
Person person = new Person.Builder().name("tom").age(3).build();
}
}
With the above code, when I right click the "name" variable and select analyse dataflow to here, I am able to see the dataflow. As shown in screenshot:
Example 2 - with Lombok:
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
#NoArgsConstructor
#Builder
#Getter
public class Person {
private String name;
private int age;
}
public class Main {
public static void main(String[] args) {
Person person = Person.builder().name("tom").age(3).build();
}
}
With the above code example, selecting 'analyse data flow to here' on the name field will show the variable name, but with no tree to expand as shown in the screenshot.
"Analyze data flow to here" will not work with generated code provided by Lombok annotations.
During the last hours I read many StackOverflow questions and articles, but none of the advices helped. What I tried:
Add #JsonCreator and #JsonProperty to both Person and Employee classes (link)
Add #JsonDeserialize(using = EmployeeDeserialize.class) to Employee class (link)
Add Lombok as dependency, set lombok.anyConstructor.addConstructorProperties=true and add #Data / #Value annotation to both Person and Employee classes (link)
Finally, I did the deserialization manually:
String json = "{\"name\": \"Unknown\",\"email\": \"please#work.now\",\"salary\":1}";
ObjectMapper objectMapper = new ObjectMapper();
Employee employee = objectMapper.readValue(json, Employee.class);
In this way I could deserialize the JSON, but as soon as I started my spring-boot-starter-web project and called
http://localhost:8080/print?name=unknown&email=please#work.now&salary=1
I got the good old BeanInstantiationException
Failed to instantiate [Employee]: No default constructor found
I run out of ideas. Does anybod know why this worked when I did the deserialization manually? And why it throws exception when I call the REST endpoint?
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
#RestController
public class EmployeeController {
#GetMapping("print")
public void print(Employee employee) {
System.out.println(employee);
}
}
public class Person {
private final String name;
#JsonCreator
public Person(#JsonProperty("name") String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public class Employee extends Person {
private final String email;
private final int salary;
#JsonCreator
public Employee(
#JsonProperty("name") String name,
#JsonProperty("email") String email,
#JsonProperty("salary") int salary) {
super(name);
this.email = email;
this.salary = salary;
}
public String getEmail() {
return email;
}
public int getSalary() {
return salary;
}
}
You’re implementing JSON deserialisation, yet you’re not using any JSON.
Change to use #PostMapping on your controller method and use something like Postman or cURL to send the JSON to your /print endpoint.
I have the following Java beans:
public class Customer implements Serializable {
private Integer id;
private String name;
private Country country;
public void setId(Integer id) {
this.id=id;
}
public void setName(String n) {
this.name=n;
}
public void setCountry(Country c) {
this.country=c;
}
public void setCountryId(Integer id) {
this.country= new Country();
this.country.setId(id)
}
//...getters here
}
and
public class Country {
private Integer id;
private String code; //es, us, fr...
private void setId(Integer id) {
this.id=id;
}
//rest of setters and getters
}
and I have the following method:
#RequestMapping(value = "/customer/", method = RequestMethod.POST)
#ResponseBody
public ResponseEntity<Customer> addSecondaryCustomer(#RequestBody Customer sc) {
this.customerService.addCustomer(sc);
return new ResponseEntity<>(sc,HttpStatus.OK);
}
Using the Web Development tools I can see the server is receiving the following:
{
"name": "Pablo Test",
"countryId": 1
}
I can see that the field name is populated, but country remains null. I've tried to set a breakpoint in both setters, but none of them is being called, so it seems that the object mapper is looking for attributes, ignoring setters. ¿Why is this happening?
I am using Jackson 2.9.0 and Spring 4.2.13. It worked with older versions of Spring (4.2.0) and Jackson (2.1.4)
PS: I know I can workaround this by sending "country": { "id": 1} in my AJAX request, but I need to know what's happening here.
I just started learning Spring and tried to make a basic Spring program but I can't resolve this error. Below is the code:
Student.java
#Component
public class Student {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Configuration Class
#Configuration
#ComponentScan("springfirst1")
public class ConfigClass {
public Student getStudent(){
return new Student();
}
}
Main Class
public class SpringFirst1 {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext("ConfigClass.class");
Student s1 = context.getBean(Student.class);
s1.setName("Adam");
System.out.println(s1.getName());
}
}
Error:
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [springfirst1.Student] is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:318)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:985)
at springfirst1.SpringFirst1.main(SpringFirst1.java:13)
Following changes in the ApplicationContext argument would solve this problem.
Main Class
public class SpringFirst1 {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(ConfigClass.class);
Student s1 = context.getBean(Student.class);
s1.setName("Gaurav");
System.out.println(s1.getName());
}
public Student getStudent(){
return new Student();
}
This is not necessary if you put #Component above you class:
If you want to use java configuration you have to put #Bean above it:
#Bean
public Student getStudent(){
return new Student();
}
EDIT: Check Arun answer :-)
I have a simple project, based on this guide. I created a simple REST interface and I want it to use my database. I added Hibernate to the dependencies and created the DAO class. I'm using Spring Tool-Suite for IDE. As far as I understand I should add some beans to tell the classes what to use but I don't understand how. Here are my classes.
Application.java
package com.learnspring.projectfirst;
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Marker.java
package com.learnspring.projectfirst;
#Entity
public class Marker {
#Id
#Column
#GeneratedValue(strategy=GenerationType.AUTO)
private long id;
#Column
private double longitude;
#Column
private double latitude;
#Column
private String address;
public Marker() {
// Empty constructor
}
public Marker(long id, double longitude, double latitude, String address) {
this.id = id;
this.longitude = longitude;
this.latitude = latitude;
this.address = address;
}
//Getters and Setters
}
MarkerController.java
package com.learnspring.projectfirst.controller;
#Controller
public class MarkerController {
private Logger logger = Logger.getLogger(MarkerController.class.getName());
#Autowired
private MarkerServiceImplementation markerService;
#RequestMapping(value="/markers", method=RequestMethod.GET)
public #ResponseBody List<Marker> getMarkers(#RequestParam(value="city", defaultValue="") String city) {
return this.markerService.getAllMarkers();
}
#RequestMapping(value="/markers/new", method=RequestMethod.POST)
public #ResponseBody Marker addMarker(#RequestBody Marker marker) {
this.markerService.addMarker(marker);
return marker;
}
}
MarkerDaoImplementation.java
package com.learnspring.projectfirst.dao;
#Repository
public class MarkerDaoImplementation implements MarkerDaoInterface {
#Autowired
private SessionFactory sessionFactory;
#Override
public void addMarker(Marker marker) {
this.sessionFactory.getCurrentSession().save(marker);
}
#Override
public void deleteMarker(int markerId) {
this.sessionFactory.getCurrentSession().delete(this.getMarker(markerId));
}
#Override
public Marker getMarker(int markerId) {
return (Marker) this.sessionFactory.getCurrentSession().get(Marker.class, markerId);
}
#Override
public List<Marker> getAllMarkers() {
return this.sessionFactory.getCurrentSession().createQuery("from Marker").list();
}
}
MarkerServiceImplementation.java
package com.learnspring.projectfirst.service;
#Service
public class MarkerServiceImplementation implements MarkerServiceInterface {
#Autowired
private MarkerDaoImplementation markerDao;
#Transactional
public void addMarker(Marker marker) {
this.markerDao.addMarker(marker);
}
#Transactional
public void deleteMarker(int markerId) {
this.markerDao.deleteMarker(markerId);
}
#Transactional
public Marker getMarker(int markerId) {
return this.markerDao.getMarker(markerId);
}
#Transactional
public List<Marker> getAllMarkers() {
return this.markerDao.getAllMarkers();
}
}
And here is the file structure:
I understand that I should tell my program the database name and the columns using beans but I don't understand how. How can I link the java code to the beans? Sorry I pasted so much code, I just wanted to make sure you have everything needed. Thank you in advance!
This is the one you need: Spring Boot with MySQL
Refer this example : Spring MVC with JdbcTemplate Example
The annotations in your "Marker" class determine the MySQL table and column names (based on the class and class variable names). The tablename will be "marker", with the columns "id", "longitude", "latitude", "address".
You forgot the most important part in your code: your spring configuration. it determines how the SessionFactory instance will be initialized before being injected into your DAO class. Here you have to set an appropriate connection to the MySQL Server (e.g. via an JNDI Resource)