I am new to SpringBoot and I am trying to connect my SpringBoot App to MongoDB. The GET Request is working completely fine but the POST Request is adding a "_class" field in the data which I don't want. I did some searching and found that I have to add a #Configuration class to solve this issue but when I added the #Configuration class, I am getting the following error :
Field mongoDbFactory in com.example.demo.configuration.MongoConfig required a bean of type 'org.springframework.data.mongodb.MongoDbFactory' that could not be found.
My Confuguration class code is as follows :-
MongoConfig.java :-
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.convert.DbRefResolver;
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
import org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
#Configuration
public class MongoConfig {
#Autowired
private MongoDbFactory mongoDbFactory;
#Autowired
private MongoMappingContext mongoMappingContext;
#Bean
public MappingMongoConverter mappingMongoConverter() {
DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory);
MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver,
mongoMappingContext);
converter.setTypeMapper(new DefaultMongoTypeMapper(null));
return converter;
}
}
Controller.java :-
import com.example.demo.model.Todo;
import com.example.demo.services.TodoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
#RestController
public class Controller {
#Autowired
private TodoService todoService;
#GetMapping("/")
public List<Todo> getTodos() {
return todoService.getTodos();
}
#PostMapping("/")
public Todo addTodo(#RequestBody Todo todo) {
return todoService.addTodo(todo);
}
}
TodoService.java :-
import com.example.demo.model.Todo;
import java.util.List;
public interface TodoService {
public List<Todo> getTodos();
public Todo addTodo(Todo todo);
}
TodoServiceImplementation.java :-
import com.example.demo.model.Todo;
import com.example.demo.repository.TodoRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
#Service
public class TodoServiceImplementation implements TodoService{
#Autowired
private TodoRepository todoRepository;
#Override
public List<Todo> getTodos() {
return todoRepository.findAll();
}
#Override
public Todo addTodo(Todo todo) {
return todoRepository.save(todo);
}
}
It is asking me to do the following action :-
Consider defining a bean of type 'org.springframework.data.mongodb.MongoDbFactory' in your configuration.
Related
I am trying to connect spring boot application with MySQL for that I have created a interface with name FilterDao which extend JpaRepository class. but whenever I try to make object of implemented class in Service I got this error "Consider defining a bean of type 'com.example.filter.FilterDao' in your configuration" as I am new to spring boot I don't understand this error.
FilterApplication.java
package com.example.filter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
#SpringBootApplication(exclude = {DataSourceAutoConfiguration.class })
public class FilterApplication {
public static void main(String[] args) {
SpringApplication.run(FilterApplication.class, args);
}
}
FilterDao.java
package com.example.filter;
import com.example.filter.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.query.FluentQuery;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
//#Configuration
public interface FilterDao extends JpaRepository<Filter, Integer> {
}
FilterService.java
package com.example.filter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
#Service
public class FilterService {
#Autowired
private FilterDao filterDao;
public List<Filter> getData() {
System.out.println("----------------------HERE-------------");
return filterDao.findAll();
}
}
FilterConnector.java
package com.example.filter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
#RestController
public class FilterConnector {
#Autowired
private FilterService filterService;
#GetMapping("/home")
public List<Filter> home()
{
return this.filterService.getData();
}
}
Project Structure
Annotate FilterDao with #Repository
Seems spring has not created bean for FilterDao repository and you are trying to use that`
#Autowired
private FilterDao filterDao;`
There might different reasons for this exception. Please try the below solution.
Use #EnableJpaRepositories(basePackages = "com.example.filter") with your FilterApplication class.
Use #ComponentScan(basePackages = "com.example.*") with FilterApplication class
Use #Repoitory annotation with FilterDao interface.
Hope this helps. For more details check the below tutorial.
https://javatute.com/jpa/consider-defining-a-bean-of-type-in-your-configuration/
I'm trying to test my application, I've been trying to solve it for 3 days and I looked for stackoverflow and I still couldn't solve it.
My problem is that Autowired is always null, and even though I import everything suggested as
#RunWith( SpringRunner.class )
#SpringBootTest
public class ESGControllerTest {
#Autowired
private ESGController esgController ;
#Test
public void deveRetornarSucesso_QuandoBuscarLatLong(){
System.out.println(this.esgController);
}
}
or
#RunWith( SpringJUnit4ClassRunner.class )
#ContextConfiguration
public class ESGControllerTest {
#Autowired
private ESGController esgController ;
#Test
public void deveRetornarSucesso_QuandoBuscarLatLong(){
System.out.println(this.esgController);
}
}
is always null and gives this error
EDIT:
ESGController
package br.com.kmm.esgeniusapi.controller;
import br.com.kmm.esgeniusapi.dto.CargaDTO;
import br.com.kmm.esgeniusapi.dto.CargaFilter;
import br.com.kmm.esgeniusapi.entity.AreaEmbargada;
import br.com.kmm.esgeniusapi.entity.Carga;
import br.com.kmm.esgeniusapi.entity.ConfiguracaoCarga;
import br.com.kmm.esgeniusapi.exception.CargaException;
import br.com.kmm.esgeniusapi.inteface.HereReverseGeocode;
import br.com.kmm.esgeniusapi.inteface.HereSearch;
import br.com.kmm.esgeniusapi.service.CargaService;
import br.com.kmm.esgeniusapi.service.ConfiguracaoCargaService;
import br.com.kmm.esgeniusapi.service.IbamaService;
import br.com.kmm.esgeniusapi.service.ReverseGeocodeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.*;
import javax.annotation.security.RolesAllowed;
import java.beans.IntrospectionException;
import java.lang.reflect.InvocationTargetException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
#Slf4j
#RestController
#CrossOrigin(origins = "*", maxAge = 3600)
#RequestMapping("/api/")
#RolesAllowed("VIEW")
#Component
public class ESGController {
#Autowired
ReverseGeocodeService reverseGeocodeService;
#Autowired
IbamaService ibamaService;
#Autowired
CargaService cargaService;
#Autowired
ConfiguracaoCargaService configuracaoCargaService;
#GetMapping(path = "reverse-geocode")
public HereReverseGeocode getRoute(#RequestParam final String location) {
Double lat = Double.parseDouble(location.split(",")[0]);
Double lon = Double.parseDouble(location.split(",")[1]);
return this.reverseGeocodeService.getReverseGeocoding(lat, lon);
}
#GetMapping(path = "search")
public List<HereSearch> search(#RequestParam(name = "q") final String query) {
return this.reverseGeocodeService.search(query);
}
....{
//MORE FUNCTIONS
}
}
I edited and put the ESGController as code for more information.
Is ESGController decorated with #Controller or equivalent so that a bean of that class actually exist in the context?
Is the test class in the same package hierarchy as the rest of the application?
#SpringBootTest by default starts searching in the current package of
the test class and then searches upwards through the package
structure, looking for a class annotated with #SpringBootConfiguration
from which it then reads the configuration to create an application
context.
Have SpringBoot Java app with different classes. I am not able to inject the dependencies and initialize/access the object of one class into another . Have seen the spring doc and used the annotations (#component,#Autowired etc. ), still there is an issue.
following are the classes.
Main Class ()
package com.test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Component;
#SpringBootApplication
public class CostmanagementApplication {
public static void main(String[] args) {
SpringApplication.run(CostmanagementApplication.class, args);
}
}
Controller class
package com.test;
import javax.swing.text.rtf.RTFEditorKit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
#Component
#Controller
public class HighChartsController {
#Autowired
private RequestToken rt;
#GetMapping("/costdata")
public static String customerForm(Model model) {
//here not able to access the getToken() method
model.addAttribute("costdata", new CostDataModel());
return "costdata";
}
}
RequestToken Class
package com.test;
import java.io.IOException;
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpRequest.BodyPublishers;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.HashMap;
import java.util.stream.Collectors;
import org.json.JSONObject;
import org.springframework.stereotype.Component;
#Component
public class RequestToken {
public String getToken() throws IOException, InterruptedException {
// TODO Auto-generated method stub
// code to get the token
return token;
}
}
now eventhough , I have all annotation in place , not getting why the getToken() method is not accessible in controller class using rt object. please suggest
Okay, let's go in order.
First of all, all the annotations #Service, #Controller and #Repository are specifications from #Component, so you don't need to specify #Component and #Controller in your HighChartsController.
Actually, if you check what the annotation #Controller definition is, you'll find this:
#Component
public #interface Controller {
...
}
Secondly, I don't really know what do you mean with that you aren't able to access the getToken() method, but as you wrote it seems you tried to access to that method as an static method.
You're injecting the object, so you use the methods of the objects like in plain Java: rt.getToken(). The only difference is that the RequestToken object will be already initialized at the moment you call it.
package com.test;
import javax.swing.text.rtf.RTFEditorKit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
#Controller
public class HighChartsController {
#Autowired
private RequestToken rt;
#GetMapping("/costdata")
public static String customerForm(Model model) {
String token = rt.getToken();
...
model.addAttribute("costdata", new CostDataModel());
return "costdata";
}
}
I tried following the documentation tutorial, but I have some issues with depracated method. Specially in this line
.then(item-> ServerResponse.ok().contentType(APPLICATION_JSON).body(fromObject(item)))
The error is : Target type of a lambda conversion must be an interface.
Below is whole code. Thanks for your help
package com.learnreactivespring.learnreactivespring.handler;
import com.learnreactivespring.learnreactivespring.document.Item;
import com.learnreactivespring.learnreactivespring.repository.ItemReactiveRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.web.reactive.function.BodyInserters.fromObject;
#Component
public class ItemsHandler {
#Autowired
ItemReactiveRepository itemReactiveRepository;
public Mono<ServerResponse> getAllItems(ServerRequest serverRequest) {
return ServerResponse.ok()
.contentType(APPLICATION_JSON)
.body(itemReactiveRepository.findAll(), Item.class);
}
public Mono<ServerResponse> getOneItem(ServerRequest request) {
String itemId = request.pathVariable("id");
Mono<ServerResponse> notFound = ServerResponse.notFound().build();
Mono<Item> itemMono = this.itemReactiveRepository.findById(itemId);
return itemMono
.then(item -> ServerResponse.ok().contentType(APPLICATION_JSON).body(fromObject(item)))
.otherwiseIfEmpty(notFound);
}
}
I need to mapping two GET methods look like:
GET /tickets - Retrieves a list of tickets
GET /tickets/12 - Retrieves a specific ticket
But when I mapped this, the Spring got confused!
When I hit http://localhost:8080/tickets in the Chrome, the result on server is:
DefaultHandlerExceptionResolver : Resolved [org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'java.lang.Long'; nested exception is java.lang.NumberFormatException: For input string: "tickets"]
When I hit http://localhost:8080/tickets/12 in the Chrome, the result on server is:
QueryTranslatorFactoryInitiator : HHH000397: Using ASTQueryTranslatorFactory
My Spring controller is:
package wendelsilverio.api.ticket;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
#RestController("tickets")
public class TicketController {
#Autowired
private TicketRepository repository;
#GetMapping
public List<TicketEntity> getTickets() {
return repository.findAll();
}
#GetMapping("/{id}")
public Optional<TicketEntity> getTicket(#PathVariable("id") Long id) {
return repository.findById(Long.valueOf(id));
}
}
My unit test is:
package wendelsilverio.api.ticket;
import static org.hamcrest.CoreMatchers.is;
import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.util.Arrays;
import java.util.Optional;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
#SpringBootTest
#AutoConfigureMockMvc
#RunWith(SpringRunner.class)
public class TicketControllerRestfulTest {
#Autowired
private MockMvc mockMvc;
#MockBean
private TicketController mockTicketController;
#Test
public void getTickets() throws Exception {
given(mockTicketController.getTickets())
.willReturn(Arrays.asList(new TicketEntity(1L, "First ticket"), new TicketEntity(2L, "Second ticket")));
mockMvc.perform(get("tickets").contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk())
.andExpect(jsonPath("$[0].content", is("First ticket")))
.andExpect(jsonPath("$[1].content", is("Second ticket")));
}
#Test
public void getTicket12() throws Exception {
Optional<TicketEntity> twelveTicket = Optional.of(new TicketEntity(12L, "Twelve ticket"));
given(mockTicketController.getTicket(12L)).willReturn(twelveTicket);
mockMvc.perform(get("tickets/12").contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk())
.andExpect(jsonPath("$.id", is(12L))).andExpect(jsonPath("$.content", is("Twelve ticket")));
}
}
I'm using Java 11 and Spring Boot 2.1.6
Use
#RestController
#RequestMapping("/tickets")
...
#GetMapping
...
#GetMapping("{id}")
In your code
1) #RestController("tickets") means 'create bean named "tickets"'
2) second URL (#GetMapping("/{id}")) tells 'put ID at root' (http://localhost:8080/ID) - so controller cannot convert 'tickets' to long.