The Query Update is not updating the MySQL DB. The method updateStatusTest is being executed and pass the test, but when I look in the database the data is the same. Below is the code I used:
mysql> SELECT * FROM spring_course_db.request;
+----+---------------------+-------------------------------------------+-------+----------------+----------+
| id | creation_date | description | state | subject | owner_id |
+----+---------------------+-------------------------------------------+-------+----------------+----------+
| 1 | 2019-09-24 20:03:28 | Pretendo obter um laptop HP, de RAM 16 GB | OPEN | Novo Laptop HP | 1 |
+----+---------------------+-------------------------------------------+-------+----------------+----------+
1 row in set (0,01 sec)
The state show be IN_PROCESS.
RequestStageRepository
package com.spring.course.repository;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import com.spring.course.domain.Request;
import com.spring.course.domain.RequestStage;
import com.spring.course.enums.RequestState;
#Repository
public interface RequestStageRepository extends JpaRepository<RequestStage, Long>{
public List<RequestStage> findAllByRequestId(Long id);
#Query("UPDATE request SET state = :state WHERE id = :id")
public Request updateStatus(Long id, RequestState state);
}
RequestRepositoryTests
package com.spring.course.repository;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.spring.course.domain.Request;
import com.spring.course.domain.User;
import com.spring.course.enums.RequestState;
#FixMethodOrder(MethodSorters.NAME_ASCENDING)
#RunWith(SpringRunner.class)
#SpringBootTest
public class RequestRepositoryTests {
#Autowired
private RequestRepository requestRepository;
#Test
public void AsaveTest() {
User owner = new User();
owner.setId(1L);
Request request = new Request(null, "Novo Laptop HP", "Pretendo obter um laptop HP", new Date(), RequestState.OPEN, owner, null);
Request createdRequest = requestRepository.save(request);
assertThat(createdRequest.getId()).isEqualTo(1L);
}
#Test
public void updateTest() {
User owner = new User();
owner.setId(1L);
Request request = new Request(1L, "Novo Laptop HP", "Pretendo obter um laptop HP, de RAM 16 GB", null, RequestState.OPEN, owner, null);
Request updatedRequest = requestRepository.save(request);
assertThat(updatedRequest.getDescription()).isEqualTo("Pretendo obter um laptop HP, de RAM 16 GB");
}
#Test
public void getByIdTest() {
Optional<Request> result = requestRepository.findById(1L);
Request request = result.get();
assertThat(request.getSubject()).isEqualTo("Novo Laptop HP");
}
#Test
public void listTest() {
List<Request> requests = requestRepository.findAll();
assertThat(requests.size()).isEqualTo(1);
}
#Test
public void listByOwnerIdTest() {
List<Request> requests = requestRepository.findAllByOwnerId(1L);
assertThat(requests.size()).isEqualTo(1);
}
#Test
public void updateStatusTest() {
int affectedRows = requestRepository.updateStatus(1L, RequestState.IN_PROCESS);
assertThat(affectedRows).isEqualTo(1);
}
}
POM:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.spring.course</groupId>
<artifactId>spring-course2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>spring-course2</name>
<description>Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.13</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Either the native update query or JPQL update query just return int which is no of records updated and also they need #Modifying annotation Update Queries
JPQL
#Modifying
#Query("update User u set u.status = :status where u.name = :name")
int updateUserSetStatusForName(#Param("status") Integer status,
#Param("name") String name);
The return value defines how many rows the execution of the query updated.
Native
You can modify the state of the database also with a native query — we just need to add the #Modifying annotation
#Modifying
#Query(value = "update Users u set u.status = ? where u.name = ?",
nativeQuery = true)
int updateUserSetStatusForNameNative(Integer status, String name);
5.3.8. Modifying Queries from spring data jpa documentation with below example
#Modifying
#Query("update User u set u.firstname = ?1 where u.lastname = ?2")
int setFixedFirstnameFor(String firstname, String lastname);
In case if you want to update record based on id and need to return the updated record, then you can use the save method
requestRepository.save(request)
Note : Make sure you have set values to all properties otherwise you will end up seeing null or default values
Related
I am using SpringBoot to connect to Redis. I have Web dependency on SpringBoot and my intention is to write Product information to a runtime datastructure i.e., a Map. I want to test the Cache annotations that Spring provides to understand the usage.
Here is the POM.xml file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>io.fireacademy</groupId>
<artifactId>redisconnectivity</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>redisconnectivity</name>
<description>Demo project for Spring Boot & Redis connectivity</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Here is the Spring Application class
package io.fireacademy.redisconnectivity;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
#SpringBootApplication
#EnableCaching
public class RedisconnectivityApplication {
public static void main(String[] args) {
SpringApplication.run(RedisconnectivityApplication.class, args);
}
}
Here is my main controller class
package io.fireacademy.redisconnectivity.controllers;
import io.fireacademy.redisconnectivity.model.Product;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
#RestController
#RequestMapping("/products")
public class WebAppController {
private static final Logger logger = LoggerFactory.getLogger(WebAppController.class);
// This will serve as the database
private Map<String, Product> m_productDatabase = new HashMap<String, Product>();
#Cacheable(value="my-product-cache", key="#productId")
private Product getProductFromCacheOrDB(String productId)
{
logger.info("Loading the Product " + productId + " from the cache!.");
return m_productDatabase.get(productId);
}
#CacheEvict(value="my-product-cache", key="#productId")
private Product deleteFromCache(String productId)
{
logger.info("Remove the Product " + productId + " from the cache!.");
return m_productDatabase.get(productId);
}
#GetMapping(path="/")
public ResponseEntity<List<Product>> getProducts()
{
Collection<Product> allProducts = m_productDatabase.values();
List<Product> allProductsAsList = allProducts.stream().collect(Collectors.toList());
return new ResponseEntity<List<Product>>(allProductsAsList, HttpStatus.OK);
}
#GetMapping(path="/{productId}")
public ResponseEntity<Product> getProducts(#PathVariable String productId)
{
// Either from the Cache or from the DB.
Product product = getProductFromCacheOrDB(productId);
return new ResponseEntity<Product>(product, HttpStatus.OK);
}
#PostMapping(consumes = {MediaType.APPLICATION_XML_VALUE,MediaType.APPLICATION_JSON_VALUE},
produces = {MediaType.APPLICATION_XML_VALUE,MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<Product> createProduct(#RequestBody Product product)
{
m_productDatabase.put(product.getId(), product);
return new ResponseEntity<Product>(product, HttpStatus.CREATED);
}
#PutMapping(path="/{productId}",
consumes = {MediaType.APPLICATION_XML_VALUE,MediaType.APPLICATION_JSON_VALUE},
produces = {MediaType.APPLICATION_XML_VALUE,MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<Product> updateProduct(#PathVariable String productId, #RequestBody Product product)
{
m_productDatabase.put(productId, product);
return new ResponseEntity<Product>(product, HttpStatus.OK);
}
#DeleteMapping(path="/{productId}")
public ResponseEntity<Product> deleteProduct(#PathVariable String productId)
{
Product deletedProduct = getProductFromCacheOrDB(productId);
deleteFromCache(productId);
return new ResponseEntity<Product>(deletedProduct, HttpStatus.OK);
}
}
Here is my RedisConfig class
package io.fireacademy.redisconnectivity.configurations;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
#Configuration
#EnableRedisRepositories
public class RedisConfig {
#Bean
public JedisConnectionFactory connectionFactory() {
RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
configuration.setHostName("localhost");
configuration.setPort(6379);
return new JedisConnectionFactory(configuration);
}
#Bean
public RedisTemplate<String, Object> template() {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory());
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new JdkSerializationRedisSerializer());
template.setValueSerializer(new JdkSerializationRedisSerializer());
template.setEnableTransactionSupport(true);
template.afterPropertiesSet();
return template;
}
}
My application.properties looks as below:
# Redis Config
spring.cache.type=redis
spring.redis.host=localhost
spring.redis.port=6379
And I am running Redis as a docker container using this:
docker run -d -p 6379:6379 --name my-redis redis
When I inspect the docker container's logs, I see nothing happening.
D:\Development\springboot\learn_redis>docker logs -f c376f1be9be35281b900c2943fbf8ea37e1563157efb57d46ca1c74fc880bc5c
1:C 04 Jun 2022 17:49:51.854 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
1:C 04 Jun 2022 17:49:51.854 # Redis version=7.0.0, bits=64, commit=00000000, modified=0, pid=1, just started
1:C 04 Jun 2022 17:49:51.854 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
1:M 04 Jun 2022 17:49:51.854 * monotonic clock: POSIX clock_gettime
1:M 04 Jun 2022 17:49:51.858 * Running mode=standalone, port=6379.
1:M 04 Jun 2022 17:49:51.858 # Server initialized
1:M 04 Jun 2022 17:49:51.858 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
1:M 04 Jun 2022 17:49:51.858 * The AOF directory appendonlydir doesn't exist
1:M 04 Jun 2022 17:49:51.858 * Ready to accept connections
My understanding was that the Cache annotations would make the data be stored onto the Redis cache. For instance, the getProductFromCacheOrDB, should store the Product object onto the cache with the input productId as the key because of the #Cacheable annotation and a subsequent call to get this specific Product using the GET productId should not invoke the method again. But this is not happening.
Please show some pointers on what I could have missed...
Thanks,
Pavan.
Edits:
I do not see anything on Redis getting created. I enabled monitoring on Redis via the redis-cli, but see nothing.
I tried removing the RedisConfig class and see no change.
Just created a simple working example at https://github.com/bsbodden/basic-caching-spring-data-redis
What you need:
POM dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
In the app class or configurer #EnableCaching:
#SpringBootApplication
#EnableCaching
public class DemoApplication {
In the app class RedisCacheManager bean:
#Bean
public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() //
.prefixCacheNameWith(this.getClass().getPackageName() + ".") //
.entryTtl(Duration.ofHours(1)) //
.disableCachingNullValues();
return RedisCacheManager.builder(connectionFactory) //
.cacheDefaults(config) //
.build();
}
#Cacheable in your controller:
#GetMapping("/{id}")
#Cacheable("some-cache")
public SomeModel get(#PathVariable("id") String id) {
return repo.findById(id).orElse(SomeModel.of("nope"));
}
I am trying to do some crud operation using micornaut microservices in java.
But getting this error, Please if anyone can help me out.
[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.625 s <<< FAILURE! - in micronautDataAcess.MicronautDataAcessTest
[ERROR] micronautDataAcess.MicronautDataAcessTest Time elapsed: 0.623 s <<< ERROR!
java.lang.RuntimeException: Failed to load a service: Unexpected error loading bean definition [micronautDataAcess.$Repository.StudentRepository$Interce
pted$Definition]: failed to access class micronautDataAcess.Repository.StudentRepository$Intercepted from class micronautDataAcess.$Repository.StudentRe
pository$Intercepted$Definition$Reference (micronautDataAcess.Repository.StudentRepository$Intercepted and micronautDataAcess.$Repository.StudentReposit
ory$Intercepted$Definition$Reference are in unnamed module of loader 'app')
Caused by: io.micronaut.context.exceptions.BeanContextException: Unexpected error loading bean definition [micronautDataAcess.$Repository.StudentReposit
ory$Intercepted$Definition]: failed to access class micronautDataAcess.Repository.StudentRepository$Intercepted from class micronautDataAcess.$Repositor
y.StudentRepository$Intercepted$Definition$Reference (micronautDataAcess.Repository.StudentRepository$Intercepted and micronautDataAcess.$Repository.Stu
dentRepository$Intercepted$Definition$Reference are in unnamed module of loader 'app')
Caused by: java.lang.IllegalAccessError: failed to access class micronautDataAcess.Repository.StudentRepository$Intercepted from class micronautDataAces
s.$Repository.StudentRepository$Intercepted$Definition$Reference (micronautDataAcess.Repository.StudentRepository$Intercepted and micronautDataAcess.$Re
pository.StudentRepository$Intercepted$Definition$Reference are in unnamed module of loader 'app')
POM FILE -
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>micronautDataAcess</groupId>
<artifactId>micronautDataAcess</artifactId>
<version>0.1</version>
<packaging>${packaging}</packaging>
<parent>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-parent</artifactId>
<version>3.1.3</version>
</parent>
<properties>
<packaging>jar</packaging>
<jdk.version>1.8</jdk.version>
<!-- If you are building with JDK 9 or higher, you can uncomment the lines below to set the release version -->
<!-- <release.version>8</release.version> -->
<micronaut.version>3.1.3</micronaut.version>
<exec.mainClass>micronautDataAcess.Application</exec.mainClass>
<micronaut.runtime>netty</micronaut.runtime>
</properties>
<repositories>
<repository>
<id>central</id>
<url>https://repo.maven.apache.org/maven2</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-inject</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-validation</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.micronaut.test</groupId>
<artifactId>micronaut-test-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-http-client</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-http-server-netty</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-runtime</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.micronaut.data</groupId>
<artifactId>micronaut-data-jdbc</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut.sql</groupId>
<artifactId>micronaut-jdbc-hikari</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.micronaut.data</groupId>
<artifactId>micronaut-data-hibernate-jpa</artifactId>
<version>3.2.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.micronaut.build</groupId>
<artifactId>micronaut-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<!-- Uncomment to enable incremental compilation -->
<!-- <useIncrementalCompilation>false</useIncrementalCompilation> -->
<annotationProcessorPaths combine.children="append">
<path>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-http-validation</artifactId>
<version>${micronaut.version}</version>
</path>
</annotationProcessorPaths>
<compilerArgs>
<arg>-Amicronaut.processing.group=micronautDataAcess</arg>
<arg>-Amicronaut.processing.module=micronautDataAcess</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>https://repo.maven.apache.org/maven2</url>
</pluginRepository>
<pluginRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>
Controller File -
package micronautDataAcess.Controller;
import io.micronaut.core.annotation.NonNull;
import io.micronaut.http.HttpResponse;
import io.micronaut.http.annotation.*;
import jakarta.inject.Inject;
import micronautDataAcess.Model.StudentModel;
import micronautDataAcess.Services.StudentServiceInterface;
import java.util.Optional;
#Controller("/crud")
public class StudentController {
#Inject
StudentServiceInterface studentServiceInterface;
/*Endpoint for the post method */
#Post(value = "/add")
#Consumes(value = "application/json")
public HttpResponse save(#Body StudentModel crudDemoModel){
StudentModel savedCrudDemoModel = studentServiceInterface.save(crudDemoModel);
return HttpResponse.created(savedCrudDemoModel);
}
/* Endpoint for the finding */
#Get(value = "/find")
#Produces(value = "application/json")
public HttpResponse findById(#NonNull Integer sid){
Optional<StudentModel> foundModelObject = studentServiceInterface.findById(sid);
if(foundModelObject.isPresent()){
return HttpResponse.ok(foundModelObject);
}
return HttpResponse.badRequest("\'Error\':\'Id provied not found in the DB'" );
}
}
Model -
package micronautDataAcess.Model;
import javax.persistence.*;
#Entity
#Table(name = "dummystudent")
public class StudentModel {
/*All the column data*/
/* Student id */
#Id
Integer sid;
/* Student name */
#Column(name = "name", nullable = false, unique = false)
String name;
/* Getter method for sid */
public Integer getSid() {
return sid;
}
/* Setter method for the student id */
public void setSid(int sid) {
this.sid = sid;
}
/* Getter method for student name */
public String getName() {
return name;
}
/* Setter method for student name */
public void setName(String name) {
this.name = name;
}
#Override
public String toString() {
return "StudentModel {" +
"sid" + sid +
"name" + name + "}";
}
}
Repository -
package micronautDataAcess.Repository;
import io.micronaut.data.annotation.Repository;
import io.micronaut.data.repository.CrudRepository;
import micronautDataAcess.Model.StudentModel;
import java.util.Optional;
#Repository
/* Curd repository -- will accept the 2 parameters
1. object, char, string etc.
2. Will accept the Integer -- that is no primitive data type.
Here we are passing studentModel - object and Integer
*/
public interface StudentRepository extends CrudRepository<StudentModel, Integer> {
/* Save method will return the student object on save*/
StudentModel save(StudentModel studentModel);
/* Optional - if the entity is not found then it will return null otherwise it will return student
entity containing all the student column data.
*/
Optional<StudentModel> findById(Integer sid);
/* Excepted the void method for the delete operation -- */
void deleteById(Integer sid);
}
Services -
Service Interface
package micronautDataAcess.Services;
import micronautDataAcess.Model.StudentModel;
import java.util.Optional;
public interface StudentServiceInterface {
StudentModel save(StudentModel studentModel);
Optional<StudentModel> findById(Integer sid);
void deleteById(Integer sid);
}
Service Implementation
package micronautDataAcess.Services;
import io.micronaut.context.annotation.Bean;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import micronautDataAcess.Model.StudentModel;
import micronautDataAcess.Repository.StudentRepository;
import java.util.Optional;
/*Initialization of Bean and Indicating the Singleton instance */
#Singleton
#Bean
public class StudentServiceImpl implements StudentServiceInterface {
/* Injecting the Student repository here in the Service Implementation */
#Inject
StudentRepository studentRepository;
/*Here we are overriding the StudentModel object that save the method.*/
#Override
public StudentModel save(StudentModel studentModel) {
return studentRepository.save(studentModel);
}
/*Here we are overriding the StudentModel -- findbyid method.*/
#Override
public Optional<StudentModel> findById(Integer sid) {
return studentRepository.findById(sid);
}
/*Here we are overriding the StudentModel -- deleteById.*/
#Override
public void deleteById(Integer sid) {
studentRepository.deleteById(sid);
}
}
Application.yml file
micronaut:
application:
name: micronautDataAcess
datasources:
default:
url: jdbc:mysql://localhost:3306/micronautspractises
user: root
password: ""
driverClassName: com.mysql.cj.jdbc.Driver
dialect: MYSQL
flyway:
datasources:
packages-to-scan: 'StudentModel'
default:
enabled: true
So I have attached all the dependencies and other file used In program. If anyone can suggest a better way to resolve the issue.
I have configured application.properties‬ as explained here with :
server.servlet.context-path=/test
And in my #RestController I have a simple a simple #RequestMapping:
#RequestMapping(value = "/products", method = RequestMethod.GET)
But still when sending a request to http://localhost:8080/test/products I get tomcat - 404 response.
Full code:
package com.siemens;
import java.util.HashMap;
import java.util.Map;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class ProductServiceController {
private static Map<String, Product> productRepo = new HashMap<>();
static {
Product honey = new Product();
honey.setId("1");
honey.setName("Honey");
productRepo.put(honey.getId(), honey);
Product almond = new Product();
almond.setId("2");
almond.setName("Almond");
productRepo.put(almond.getId(), almond);
}
#RequestMapping(value = "/products", method = RequestMethod.GET)
public ResponseEntity<Object> getProduct() {
return new ResponseEntity<>(productRepo.values(), HttpStatus.OK);
}
}
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>siemens</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>siemens</name>
<description>Demo project for siemens</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
#SpringBootApplication:
#SpringBootApplication
public class SiemensApplication {
public static void main(String[] args) {
SpringApplication.run(SiemensApplication.class, args);
}
}
Running on tomcat 9, if there is more code or config needed please comment below, thank you.
Any request should 'know' how to get to this controller. I would suggest trying this:
#RestController
#RequestMapping("psc")
public class ProductServiceController {
#RequestMapping(value = "products", method = RequestMethod.GET)
public ResponseEntity<Object> getProduct() {
return new ResponseEntity<>(productRepo.values(), HttpStatus.OK);
}
this way you can send a GET request, to the following url:
http://localhost:8080/test/psc/products
add the #RequestMapping annotation to specify the path to this class(controller)
get rid of the "/" on every #RequestMapping path value (just a cosmetic suggestion)
Exception is:
An exception occurred while running. null: InvocationTargetException: Error creating bean with name 'machineController': Unsatisfied dependency expressed through field 'machineRepository': Error creating bean with name 'machineRepository': Invocation of init method failed; nested exception is org.springframework.data.mapping.PropertyReferenceException: No property machine found for type Machine!; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'machineRepository': Invocation of init method failed; nested exception is org.springframework.data.mapping.PropertyReferenceException: No property machine found for type Machine!
Editor for coding, is Subline, Code for the project
main
Main class for springboot application
package com.brommarest;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
importorg.springframework.data.jpa.repository.config.EnableJpaRepositories;
#SpringBootApplication
#EntityScan(basePackages = {"com.brommarest.entities" })
#EnableJpaRepositories(basePackages = {"com.brommarest.repositories"})
public class BrommaRestApplication {
public static void main(String[] args) {
SpringApplication.run(BrommaRestApplication.class, args);
}
}
Repositories repositoty file, MachineRepository.java
Repository for the Machine entity
package com.brommarest.repositories;
import com.brommarest.entities.Machine;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
import java.util.Set;
import org.springframework.data.repository.PagingAndSortingRepository;
import java.util.List;
#Repository
public interface MachineRepository extends JpaRepository<Machine, Integer> {
// custom query to search to machine by type or description
List<Machine> findBymachine_typeOrmachine_desc(String text, String
textAgain);
}
entities entity filem, Machine.java
entity class for the repository
package com.brommarest.entities;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity
public class Machine {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int machine_id;
private String machine_type;
private String machine_desc;
private String date_added;
public Machine() { }
public Machine(String machine_type, String machine_desc, String date_added)
{
this.setTitle(machine_type);
this.setDesc(machine_desc);
this.setDate(date_added);
}
public Machine(int machine_id, String machine_type, String machine_desc,
String date_added) {
this.setId(machine_id);
this.setTitle(machine_type);
this.setDesc(machine_desc);
this.setDate(date_added);
}
public int getId() {
return machine_id;
}
public void setId(int machine_id) {
this.machine_id = machine_id;
}
public String getTitle() {
return machine_type;
}
public void setTitle(String machine_type) {
this.machine_type = machine_type;
}
public String getDesc() {
return machine_desc;
}
public void setDesc(String machine_desc) {
this.machine_desc = machine_desc;
}
public String getDate() {
return date_added;
}
public void setDate(String date_added) {
this.date_added = date_added;
}
#Override
public String toString() {
return "Machine{" +
"machine_id=" + machine_id +
", machine_type='" + machine_type + '\'' +
", machine_desc='" + machine_desc + '\'' +
", date_added='" + date_added + '\'' +
'}';
}
}
Controller MachineController.java
Controller for the project
package com.brommarest.controllers;
import com.brommarest.entities.Machine;
import com.brommarest.repositories.MachineRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
#RestController
public class MachineController {
#Autowired
MachineRepository machineRepository;
#GetMapping("/machine")
public List<Machine> index(){
return machineRepository.findAll();
}
#GetMapping("/machine/{machine_id}")
public Machine show(#PathVariable String machine_id){
int machineId = Integer.parseInt(machine_id);
return machineRepository.findOne(machineId);
}
#PostMapping("/machine/search")
public List<Machine> search(#RequestBody Map<String, String> body){
String searchTerm = body.get("text");
return machineRepository.findBymachine_typegOrmachine_desc(searchTerm,
searchTerm);
}
#PostMapping("/machine")
public Machine create(#RequestBody Map<String, String> body){
String machine_type = body.get("machine_type");
String machine_desc = body.get("machine_desc");
String date_added = body.get("date_added");
return machineRepository.save(new Machine(machine_type, machine_desc,
date_added));
}
#PutMapping("/machine/{machine_id}")
public Machine update(#PathVariable String machine_id, #RequestBody
Map<String, String> body){
int machineId = Integer.parseInt(machine_id);
// getting machine
//Machine machine = MachineRepository.findOne(machineId);
Machine machine = machineRepository.findOne(machineId);
machine.setTitle(body.get("machine_type"));
machine.setDesc(body.get("machine_desc"));
return machineRepository.save(machine);
}
#DeleteMapping("/machine/{machine_id}")
public boolean delete(#PathVariable String machine_id){
int machineId = Integer.parseInt(machine_id);
machineRepository.delete(machineId);
return true;
}
}
application.properties
spring.jpa.database=POSTGRESQL
spring.datasource.platform=postgres
spring.jpa.show-sql=true
spring.database.driverClassName=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/postgres
spring.datasource.username=postgres
spring.datasource.password=default
logging.level.org.springframework.web: DEBUG
logging.level.org.hibernate: ERROR
pom file
<groupId>com.brommarest</groupId>
<artifactId>brommarest</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Bromma-REST</name>
<description>Bromma-REST API'S project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.0.RELEASE</version>
<relativePath/>
<!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-social-twitter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-beanutils/commons-
beanutils -->
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Interface signature should follow name convention. Spring generates queries based on the method signature and it cannot.
I guess you should capitalize property names. Please try this:
List<Machine> findByMachine_typeOrMachine_desc(String text, String
textAgain);
No underscore ("_") business is Java, unless you know what exactly you are doing. Rename all the methods and field names to use camelCase. Spring is expecting things to be in a certain way, otherwise it will misbehave.
#GetMapping("/machine/{machine_id}") this "_" is fine
But this public Machine show(#PathVariable String machine_id){ is not
I decided to try out Spring Boot on Heroku and everything works perfectly...well, apart from the database!
I tried many different things to make it work, followed a lot of different approaches I found online and also from questions on StackOverflow, but nothing seems to work for me.
I'm going to post only the bare minimum of the app I'm trying to deploy.
The below is desployed fine, but when I'm trying to POST something I get the following as response:
{"timestamp":1413600470146,"error":"Unsupported Media Type","status":415,"message":"Unsupported Media Type"}
And when I'm trying to GET, I get the following exception in the Heroku logs:
nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet] with root cause
org.postgresql.util.PSQLException: ERROR: relation "exampleEntity" does not exist
Position: 109
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2103)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1836)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:257)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:512)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:388)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeQuery(AbstractJdbc2Statement.java:273)
at org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:96)
....
So, I have the following pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>project-name</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.0.2.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<jersey.version>2.8</jersey.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey</groupId>
<artifactId>jersey-bom</artifactId>
<version>${jersey.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.1-901-1.jdbc4</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-spring3</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-inmemory</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>1.5.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.skyscreamer</groupId>
<artifactId>jsonassert</artifactId>
<version>1.2.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>http://repo.spring.io/libs-release</url>
</repository>
<repository>
<id>org.jboss.repository.releases</id>
<name>JBoss Maven Release Repository</name>
<url>https://repository.jboss.org/nexus/content/repositories/releases</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>http://repo.spring.io/libs-release</url>
</pluginRepository>
</pluginRepositories>
</project>
Then my Main class is:
package com.example;
import org.glassfish.jersey.servlet.ServletContainer;
import org.glassfish.jersey.servlet.ServletProperties;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.embedded.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import com.example.config.JerseyConfig;
#EnableAutoConfiguration
#ComponentScan
#EnableJpaRepositories
public class Main {
#Bean
public ServletRegistrationBean jerseyServlet() {
ServletRegistrationBean registration = new ServletRegistrationBean(new ServletContainer(), "/rest/*");
// our rest resources will be available in the path /rest/*
registration.addInitParameter(ServletProperties.JAXRS_APPLICATION_CLASS, JerseyConfig.class.getName());
return registration;
}
public static void main(String[] args) {
new SpringApplicationBuilder(Main.class).showBanner(false).run(args);
}
}
I also have a JerseyConfig (for Jersey configuration):
package com.example.config;
import org.glassfish.jersey.filter.LoggingFilter;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.spring.scope.RequestContextFilter;
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
register(RequestContextFilter.class);
packages("com.example");
register(LoggingFilter.class);
}
}
And a BasicDataSource for the database:
package com.example.config;
import java.net.URI;
import java.net.URISyntaxException;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
#Configuration
public class SimpleDbConfig {
#Bean
public DataSource dataSource() throws URISyntaxException {
URI dbUri;
try {
String username = "username";
String password = "password";
String url = "jdbc:postgresql://localhost/dbname";
String dbProperty = System.getProperty("database.url");
if(dbProperty != null) {
dbUri = new URI(dbProperty);
username = dbUri.getUserInfo().split(":")[0];
password = dbUri.getUserInfo().split(":")[1];
url = "jdbc:postgresql://" + dbUri.getHost() + dbUri.getPath();
}
BasicDataSource basicDataSource = new BasicDataSource();
basicDataSource.setUrl(url);
basicDataSource.setUsername(username);
basicDataSource.setPassword(password);
return basicDataSource;
} catch (URISyntaxException e) {
//Deal with errors here.
throw e;
}
}
}
Finally, I have my REST resource:
package com.example.resource;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.example.service.ExampleService;
import com.example.transport.ExampleEntity;
#Path("/entities")
#Component
public class ExampleResource {
private ExampleService exampleService;
#Autowired
public ExampleResource(ExampleService exampleService) {
this.exampleService = exampleService;
}
#POST
#Path("/new")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public ExampleEntity createNewEntity(ExampleEntity entity) {
return exampleService.createNewEntity(entity);
}
#GET
#Path("/{id}")
#Produces(MediaType.APPLICATION_JSON)
public ExampleEntity getExampleDetails(#PathParam("id") Long id) {
return exampleService.findEntity(id);
}
}
A service class:
package com.example.service;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.example.repositories.ExampleRepository;
import com.example.transport.ExampleEntity;
#Service
public class ExampleService {
private ExampleRepository repo;
#Autowired
public ExampleService(ExampleRepository repo) {
this.repo = repo;
}
#Transactional
public ExampleEntity createNewEntity(ExampleEntity entity) {
ExampleEntity savedEntity = repo.save(entity);
return savedEntity;
}
#Transactional
public ExampleEntity findEntity(Long id) {
return repo.findOne(id);
}
}
The entity:
package com.example.transport;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
#Entity
public class ExampleEntity {
#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 name;
}
public void setName(String name) {
this.name = name;
}
}
And finally the repo interface:
package com.example.repositories;
import org.springframework.data.repository.CrudRepository;
import com.example.transport.ExampleEntity;
public interface MeetingRepository extends CrudRepository<ExampleEntity, Long> {
}
Any help is much appreciated!
Edit:
The Procfile I'm using is the following:
web: java -Dserver.port=$PORT -Ddatabase.url=$DATABASE_URL $JAVA_OPTS -jar target/project-name-0.0.1-SNAPSHOT.jar
It seems you have not created the table exampleEntity yet. I can see you are using postgreSQL, so please use heroku config | grep HEROKU_POSTGRESQL to check if you have one enabled in heroku (also its name and url). If not, enable it in your heroku account manager, it's a free plugin.
Use heroku pg:promote HEROKU_POSTGRESQL_<color of your db> to promote it to the main one. You will get some output like:
Promoting HEROKU_POSTGRESQL_BROWN_URL (DATABASE_URL) to DATABASE_URL... done
Now you should use DATABASE_URL environment variable to connect to your db. Heroku will provide it for you. (Also please post your Procfile too).
Using the url connect to your database and add the required table with a schema that maches your ExampleEntity class.
Side notes
Connecting to heroku db:
https://devcenter.heroku.com/articles/connecting-to-heroku-postgres-databases-from-outside-of-heroku
If you didn't understand some heroku stuff I wrote, their documentation is really well written:
https://devcenter.heroku.com/categories/heroku-architecture
https://devcenter.heroku.com/articles/heroku-postgresql
If I understood you all wrong and you're running your app on localhost and didn't deploy it to heroku yet, then just add the table to your local db instance.
Example I use with automatic table generation
Apart from DATABASE_URL, which is always there, Heroku creates 3 environment variables at Runtime. They are:
JDBC_DATABASE_URL
JDBC_DATABASE_USERNAME
JDBC_DATABASE_PASSWORD
As you may be aware, Spring Boot will automatically configure your database if it finds spring.datasource.* properties in your application.properties file. Here is an example of my application.properties
spring.datasource.url=${JDBC_DATABASE_URL}
spring.datasource.username=${JDBC_DATABASE_USERNAME}
spring.datasource.password=${JDBC_DATABASE_PASSWORD}
spring.jpa.show-sql=false
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=update
Hibernate / Postgres Dependencies
In my case I'm using Hibernate (bundled in spring-boot-starter-jpa with PostgreSQL, so I needed the right dependencies in my build.gradle:
dependencies {
compile("org.springframework.boot:spring-boot-starter-data-jpa")
compile('org.postgresql:postgresql:9.4.1212')
}