I am trying to post data from postman via my Spring Boot 2 Application with Spring Data JPA into a MySQL Database. All I get is a 404 Error.
Main
#SpringBootApplication
public class ProfileApplication {
public static void main(String[] args) {
SpringApplication.run(ProfileApplication.class, args);
}
}
Entity
#Entity
public #Data class Profile {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String profileText;
}
Controller
#RestController
#RequestMapping(value = "/profile", produces = { MediaType.APPLICATION_JSON_VALUE })
public class ProfileController {
#Autowired
private ProfileRepository profileRepository;
public ProfileRepository getRepository() {
return profileRepository;
}
#GetMapping("/profile/{id}")
Profile getProfileById(#PathVariable Long id) {
return profileRepository.findById(id).get();
}
#PostMapping("/profile")
Profile createOrSaveProfile(#RequestBody Profile newProfile) {
return profileRepository.save(newProfile);
}
}
Repository
public interface ProfileRepository extends CrudRepository<Profile, Long> {
}
application.propterties
server.port = 8080
spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://localhost:3306/profiledb
spring.datasource.username=root
spring.datasource.password=
server.servlet.context-path=/service
It seems that in your ProfileController, you have defined twice the profile endpoint (first at the class level, and second on the methods). The solution would be to remove one of them:
#RestController
#RequestMapping(value = "/profile", produces = { MediaType.APPLICATION_JSON_VALUE })
public class ProfileController {
#Autowired
private ProfileRepository profileRepository;
public ProfileRepository getRepository() {
return profileRepository;
}
// Notice that I've removed the 'profile' from here. It's enough to have it at class level
#GetMapping("/{id}")
Profile getProfileById(#PathVariable Long id) {
return profileRepository.findById(id).get();
}
// Notice that I've removed the 'profile' from here. It's enough to have it at class level
#PostMapping
Profile createOrSaveProfile(#RequestBody Profile newProfile) {
return profileRepository.save(newProfile);
}
}
Which url? Valid url must look like:
GET: http://localhost:8080/service/profile/profile/1
POST: http://localhost:8080/service/profile/profile
Related
I have some trouble to get the right config for jpa repository for elasticsearch.
The configuration is for aws elasticsearch
#Component
public class AmazonElasticSearchConnector implements AmazonElasticSearchClient {
#Value("${elasticsearch.endpoint}")
private String elasticSearchEndpoint;
#Bean
public RestHighLevelClient createClient() {
return createClient(elasticSearchEndpoint);
}
}
and then i have another config
#Configuration
public class ESConfig {
#Autowired
private RestHighLevelClient client;
#Bean
public ElasticsearchOperations elasticsearchTemplate() {
return new ElasticsearchRestTemplate(client);
}
}
Here my Entity
#Entity
#Document(indexName = "item")
public class SupplierItemFilterResponseEntity {
#ElementCollection
private List<String> searchCollect;
#Id
private int id;
....
and my nested Entity
#Entity
#Document(indexName = "item")
public class TechnologyFilterEntity {
public int getTechnologyID() {
return technologyID;
}
public void setTechnologyID(int technologyID) {
this.technologyID = technologyID;
}
....
and I have a repository
public interface SupplierItemFilterESRepository extends
ElasticsearchRepository<SupplierItemFilterResponseEntity, Integer> {
}
And then the service that encountered an error
#Autowired
private RestHighLevelClient client;
#Autowired
private SupplierItemFilterESRepository supplierItemFilterESRepository;
public Page<SupplierItemFilterResponseEntity> getSupplierWithGivenFiltersPagination(Pageable pageable) {
return supplierItemFilterESRepository.findAll(pageable);
}
....
and the Error i get is following
No property indexWithoutRefresh found for type SupplierItemFilterResponseEntity!
Im on it for 2 days now, and my expertise is over. Maybe someone has the same problem.
Cheers and thank you if you can help!
I have the most common project on Spring Boot MVC. and I'm trying to write update data via PUT.
#RestController
#RequestMapping(CommentController.PATH)
public class CommentController {
public final static String PATH = "/comments";
#Autowired
private CommentService service;
#PutMapping("/{id}")
public Comment update(#RequestBody Comment comment, #PathVariable Long id) {
return service.update(id, comment);
}
}
#Service
public class CommentService {
#Autowired
private CommentRepository repository;
public Comment update(Long id, Comment entity) {
Optional<Comment> optionalEntityFromDB = repository.findById(id);
return optionalEntityFromDB
.map(e -> saveAndReturnSavedEntity(entity, e))
.orElseThrow(getNotFoundExceptionSupplier("Cannot update - not exist entity by id: " + id, OBJECT_NOT_FOUND));
}
private Comment saveAndReturnSavedEntity(Comment entity, Comment entityFromDB) {
entity.setId(entityFromDB.getId());
return repository.save(entity);
}
}
#Repository
public interface CommentRepository extends JpaRepository<Comment, Long> {
}
#Entity
public class Comment {
#Id
#Column
#GeneratedValue(strategy = GenerationType.IDENTITY)
protected Long id;
#Column(name = "name")
protected String name;
}
then I write a test with the ability to check for updated data:
#SpringBootTest
#RunWith(SpringRunner.class)
#Transactional
// DBUnit config:
#DatabaseSetup("/comment.xml")
#TestExecutionListeners({
TransactionalTestExecutionListener.class,
DependencyInjectionTestExecutionListener.class,
DbUnitTestExecutionListener.class
})
public class CommentControllerTest {
private MockMvc mockMvc;
private static String route = PATH + "/{id}";
#Autowired
private CommentController commentController;
#Autowired
private CommentRepository commentRepository;
#PersistenceContext
private EntityManager entityManager;
#Before
public void setup() {
mockMvc = MockMvcBuilders.standaloneSetup(commentController)
.build();
}
#Test
public void update_ShouldReturnCreated2() throws Exception {
int id = 1;
String name = "JohnNew";
Comment expectedComment = new Comment();
expectedComment.setName(name);
ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
String json = ow.writeValueAsString(expectedComment);
this.mockMvc.perform(put(route, id)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(json))
.andDo(print());
entityManager.clear();
entityManager.flush();
Comment commentUpdated = commentRepository.findById(1L).get();
assertThat(commentUpdated.getName(), equalTo(name)); // not equals!
}
}
comment.xml:
<dataset>
<Comment id="1" name="John" />
</dataset>
but the problem is that the data is not updated.
If you enable the logging of Hibernat, then there is also no update request to the database.
What am I doing wrong?
You are missing off the #Transactional annotation from your CommentService. Whilst it can be better to add it at the per-method level, try adding it to class level to verify this fixes things:
#Service
#Transactional
public class CommentService {
I'm building a microservice architecture with Spring Framework, Feign and Eureka.
Shop works as an API Gateway, realised with Zuul (no database)
Each microservice has its own h2 database.
The CustomerService can call cart mappings with Feign
Example: I have a "Shop" and want to create a customer with a cart in one method in the service itself.
How can I call methods in the ShopService, to manage the other Services without having relationships to the other services? Please let me know if you need code examples.
CustomerController.java:
#ComponentScan
#RestController
public class CustomerController {
final Customer2CartConnectorRequester customer2CartConnectorRequester;
final Customer2OrderConnectorRequester customer2OrderConnectorRequester;
#Autowired
private CustomerJpaRepository customerJpaRepository;
#Autowired
public CustomerController(Customer2CartConnectorRequester customer2CartConnectorRequester,
Customer2OrderConnectorRequester customer2OrderConnectorRequester) {
this.customer2CartConnectorRequester = customer2CartConnectorRequester;
this.customer2OrderConnectorRequester = customer2OrderConnectorRequester;
}
#GetMapping("/list")
#ResponseBody
public List<CustomerEntity> getCustomers() {
return customerJpaRepository.findAll();
}
#RequestMapping("/{customerId}")
#ResponseBody
public Optional<CustomerEntity> getCustomer(#PathVariable("customerId") int customerId) {
return customerJpaRepository.findById(customerId);
}
// Client to Server
// POST über z.B. Postman Client
#PostMapping("/customer")
public CustomerEntity addCustomer(#RequestBody CustomerEntity customerEntity) {
customerJpaRepository.save(customerEntity);
return customerEntity;
}
#DeleteMapping("customer/{customerId}")
public String deleteCustomer(#PathVariable int customerId) {
CustomerEntity a = customerJpaRepository.getOne(customerId);
customerJpaRepository.delete(a);
return "deleted";
}
#PutMapping("/customer")
public CustomerEntity updateCustomer(#RequestBody CustomerEntity customerEntity) {
customerJpaRepository.save(customerEntity);
return customerEntity;
}
/// CONNECTOR REQUESTER ///
#GetMapping("/cart")
public List<?> getCart() {
return customer2CartConnectorRequester.getCart();
}
#GetMapping("/orders")
public List<?> getOrders() {
return customer2OrderConnectorRequester.getOrders();
}
}
Update:
I tried using a POST-Method to send data via Postman Client like this, but it seems like there is still something wrong:
Shop2CustomerConnectorRequester:
#FeignClient("customermicroservice")
public interface Shop2CustomerConnectorRequester {
#RequestMapping(value = "/list", method = RequestMethod.POST)
public ResponseEntity<String> createCustomer(Map<String, ?> queryMap);
}
ShopController:
#ComponentScan
#RestController
public class ShopController {
final Shop2CustomerConnectorRequester shop2CustomerConnectorRequester;
#Autowired
private ShopJpaRepository shopJpaRepository;
#Autowired
public ShopController(Shop2CustomerConnectorRequester shop2CustomerConnectorRequester) {
this.shop2CustomerConnectorRequester = shop2CustomerConnectorRequester;
}
#GetMapping("/customer")
public ResponseEntity<String> createCustomer(Map<String, ?> queryMap) {
return shop2CustomerConnectorRequester.createCustomer(queryMap);
}
}
I am using Spring Boot 1.5.3.RELEASE to build a new MVC application.
I have a Customer entity as follows:
#Entity
public class Customer {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#Column(name = "name", length = 100, nullable = false)
private String name;
#Column(name = "enabled", nullable = false)
private boolean enabled;
}
I have a CustomerRepository as follows:
public interface CustomerRepository extends CrudRepository<Customer, Integer> {
}
I have a CustomerService as follows:
#Service
public class CustomerService {
#Autowired
CustomerRepository customerRepository;
#Autowired
CustomerMapper customerMapper;
public CustomerDto save(CustomerDto customerDto) {
Customer customer = customerMapper.map(customerDto, Customer.class);
customerRepository.save(customer);
return customerMapper.map(customer, CustomerDto.class);
}
public CustomerDto findById(int id) {
Customer customer = customerRepository.findOne(id);
return customerMapper.map(customer, CustomerDto.class);
}
}
My application is defined as:
#SpringBootApplication
public class CoreApplication {
public static void main(String[] args) {
SpringApplication.run(CoreApplication.class, args);
}
}
My JPA configuration is:
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories
public class PersistenceConfig {
}
I have written a test as follows:
#RunWith(SpringRunner.class)
#SpringBootTest
public class ServiceTests {
#Autowired
CustomerService customerService;
#Test
public void testCustomerService() {
CustomerDto customerDtoIn = new CustomerDto();
customerDtoIn.setName("Test Customer");
customerDtoIn.setEnabled(true);
customerService.save(customerDtoIn);
CustomerDto customerDtoOut = customerService.findById(customerDtoIn.getId());
assertThat(customerDtoOut).isEqualTo(customerDtoIn);
}
}
The structure I have followed is:
com.app.core <- CoreApplication lives here
com.app.core.repositories <- Repositories here
com.app.core.services <- Services here
However, when I try to run this test case I get the following:
org.springframework.beans.factory.NoSuchBeanDefinitionException
No qualifying bean of type 'com.app.core.repositories.CustomerRepository' available
Can someone tell me why the dependency injection is failing? From reading the spring-boot docs #SpringBootTest and #RunWith(SpringRunner.class) are all I need to test my service layer.
you have to add base package and repository base package into ApplicationContext.xml. yo can use below code:-
<context:component-scan annotation-config="true"
base-package="com.demo.test" />
<jpa:repositories base-package="com.demo.test.repository" />
My springboot app tries to read data from two datasources(emwbis and backupemwbis). I've followed the below link in configuring my springboot app to read data from two different datasources.
http://www.baeldung.com/spring-data-jpa-multiple-databases
The current problem with my app is it is always reading data from the primary datasource(emwbis). I've written below code.
Model classes for primary and backup datasources:
package com.jl.models.primary;
#Entity
#Table(name = "crsbis",schema="emwbis")
#Data
public class CrsBIS {
#Id
private String id;
#NotNull
private String email;
package com.jl.models.backup;
import lombok.Data;
#Entity
#Table(name = "crsbis",schema="backupemwbis")
#Data
public class CrsBIS {
#Id
private String id;
#NotNull
private String email;
Datasource config classes for primary and backup datasources:
#Configuration
#PropertySource("classpath:persistence-multiple-db.properties")
#EnableJpaRepositories(basePackages = "com.jl.dao.backup", entityManagerFactoryRef = "crsBISBackUpEntityManager", transactionManagerRef = "crsBISBackupTransactionManager")
public class BackupCrsBISDatabaseConfig {
#Configuration
#PropertySource("classpath:persistence-multiple-db.properties")
#EnableJpaRepositories(basePackages = "com.jl.dao.primary", entityManagerFactoryRef = "crsBISEntityManager", transactionManagerRef = "crsBISTransactionManager")
public class CrsBISDatabaseConfig {
Repository interfaces for primary and backup datasources:
#Transactional
public interface CrsBISRepository extends JpaRepository<CrsBIS, String> {
public CrsBIS findById(String id);
}
#Transactional
public interface CrBisBackupRepository extends JpaRepository<CrsBIS, String>{
public CrsBIS findById(String id);
}
Persistent db proeprties file :
jdbc.driverClassName=com.mysql.jdbc.Driver
crsbis.jdbc.url=jdbc:mysql://localhost:3306/emwbis
backupcrsbis.jdbc.url=jdbc:mysql://localhost:3306/backupemwbis
jdbc.user=root
jdbc.pass=Password1
Controller class to test both the datasources :
#Controller
public class CrsBISController {
#Autowired
private CrsBISRepository crsBISRepository;
#Autowired
private CrBisBackupRepository crsBackupRepository;
#RequestMapping("/get-by-id")
#ResponseBody
public String getById(String id){
String email="";
try{
CrsBIS crsBIS = crsBISRepository.findById(id);
email = String.valueOf(crsBIS.getEmail());
}catch (Exception e) {
e.printStackTrace();
return "id not found!";
}
return "The email is : "+email;
}
#RequestMapping("/get-by-id-backup")
#ResponseBody
public String getByIdFromBackup(String id){
String email="";
try{
com.jl.models.backup.CrsBIS crsBIS = crsBackupRepository.findById(id);
email = String.valueOf(crsBIS.getEmail());
}catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
return "id not found!";
}
return "The email is : "+email;
}
Although, I've separated the database schemas in the model classes and in the database config file, both the methods in the controller class hit the same database (emwbis). I want getByIdFromBackup method in controller class to read the data from secondary database (backupemwbis).
Can someone please let me know the mistake in my code? Or you can suggest/guide me to achieve my goal?
From the first configuration file you're creating a primary datasource bean definition with the name myDatasource and in the second emf you're injecting the same datasource reference.
The Bean causing the problem is this
#Bean
#Primary
public DataSource myDataSource()
Just change the second Bean datasource name and use it in the second EMF.
public class BackupCrsBISDatabaseConfig {
...
#Bean
public DataSource backupDS() {
....
#Bean
public LocalContainerEntityManagerFactoryBean crsBISBackUpEntityManager() {
....
em.setDataSource(backupDS());
}
}
Hope this fixes it.
You have to explicitly request a TransactionManager implementation in your #Transactional usage:
#Transactional("crsBISTransactionManager")
//..
#Transactional("crsBISBackupTransactionManager")
//..