I have a problem with sqlite3, hibernate and spring.In fact, if I start the program and call the createType () method that creates a type and after that I call the getAllTypes () method I have the values of the object I just created appear in the browser.But if I check with a "select * from type" in my table type to see if the object was added in my table, I have no record. In addition, as soon as I restart the program and I call the method getAllTypes () to view the data of my table I have nothing that appears in my browser.Again, for each startup looks like the ID is reset since it starts at 1 (for example if after starting my program I try to insert 2 objects with the method createType () I have: ID = 1 and ID = 2 which appears in my browser). So if my data is not saved in my table where have they been? I made 2 recordings manually in my table and I also can not get these 2 records with the methods getAllTypes () which is supposed to send me all the records of my table. I'm told that there may be a communication problem between my program and my database.Thank you in advance for your help!!!
This is how I call my methods in browsers:
http://localhost:8080/types/getAllTypes
http://localhost:8080/types/insert
application.yml
spring:
profile:dev
jpa:
hibernate:
hbm2ddl.auto:update
properties:
hibernate:
dialect:org.hibernate.dialect.SQLiteDialect
datasource:
url:jdbc:sqlite:C:\Users\user pc\Desktop\PDF\testrest.db
username:user
password:password
driverClassName:org.sqlite.JDBC
My dependency in my pom.xml for the configuration of sqlite,hibernate and spring :
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.8.RELEASE</version>
<type>pom</type>
</parent>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.12.Final</version>
</dependency>
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.20.1</version>
</dependency>
<dependency>
<groupId>com.zsoltfabok</groupId>
<artifactId>sqlite-dialect</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.196</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.2.12.Final</version>
</dependency>
<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.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.0</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
<dependency>
My table type:
CREATE TABLE IF NOT EXISTS type(
idType integer NOT NULL PRIMARY KEY AUTOINCREMENT,
description varchar(256) NOT NULL
)
My entities type:
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="typedifficulte")
public class Type {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long idType;
private String description;
public Type() {
}
public Type(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public long getIdType() {
return idType;
}
public void setIdType(long idType) {
this.idType = idType;
}
}
My interface TypeService :
public interface TypeService {
Collection<Type> getAllTypes();
Type createType(Type type);
}
My TypeServiceImpl :
import javax.annotation.Resource;
import org.apache.commons.collections4.IteratorUtils;
import org.springframework.stereotype.Service;
#Service(value="typeService")
public class TypeServiceImpl implements TypeService {
#Resource
private TypeRepository typeRepository;
#Override
public Collection<Type> getAllTypes() {
return IteratorUtils.toList(this.typeRepository.findAll().iterator());
}
#Override
public Type createType(Type type) {
return this.typeRepository.save(type);
}
public TypeRepository getTypeRepository() {
return typeRepository;
}
public void setTypeRepository(TypeRepository typeRepository) {
this.typeRepository = typeRepository;
}
}
My TypeRepository :
public interface TypeRepository extends CrudRepository<Type,Long> {
Type findByDescription(String description);
}
My Controller :
#RestController
#RequestMapping(value ="/types")
public class TypeController {
#Resource
private TypeService typeService;
#RequestMapping(value= "/getAllTypes", method = RequestMethod.GET)
public Collection<Type> getAllTypes() {
return this.typeService.findAll();
}
#RequestMapping(value = "/insert",method = RequestMethod.GET)
public Type createType() {
return this.typeService.createType(new Type("test"));
}
}
And finally my startup class :
#Configuration
#EnableAutoConfiguration
#ComponentScan
public class MainLauncher {
public static void main(String[] args) {
SpringApplication.run(MainLauncher.class, args);
}
}
Related
I am trying to implement a reactive architecture to my Spring+MongoDB+GraphQL app, have followed some tutorials on that, but whenever I return a Publisher<Page> from my GraphQLQueryResolver - I get this error:
2022-11-17 09:18:56.316 ERROR 14166 --- [nio-8081-exec-1]
g.servlet.DefaultGraphQLErrorHandler : Error executing query
(ExceptionWhileDataFetching): Exception while fetching data (/getPages/id) : Expected
source object to be an instance of 'com.example.jobscraperspringserver.types.Page' but
instead got 'reactor.core.publisher.FluxJust'
I've played with the returned object (tried Flux<Page>, Publisher<List<Page>> and other configurations) as well as a type in the schema.graphqls, but none of them work. Besides, that's what supposed to be working in the majority of tutorials as well as some other SO issues, so I suppose that's either a bug somewhere in my code or an architectural flaw (i.e. some faulty dependency that doesn't support the type convertion).
Here is my code:
PageQuery.java
#Component
public class PageQuery implements GraphQLQueryResolver {
#Autowired
PageService pageService;
public Publisher<Page> getPages() {
return pageService.getPages();
}
}
PageService.java
#Service
public class PageService {
public Flux<Page> getPages() {
return Flux.just(new Page(12));
}
}
schema.graphqls
type Page {
id: Int!
host: String
}
type Query {
getPages: Page
}
pom.xml
...
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- GraphQL -->
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>5.0.2</version>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java-tools</artifactId>
<version>5.2.4</version>
</dependency>
<!-- GraphQL subscriptions -->
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
</dependency>
<!-- MongoDB -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
<version>2.6.3</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-reactivestreams</artifactId>
</dependency>
<!-- h2 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<!-- JWT -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<!-- Spring Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>2.0.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
<!-- WebFlux -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<version>2.6.4</version>
</dependency>
</dependencies>
...
UPDATE
Apparently com.graphql-java doesn't handle WebFlux, so I've replaced
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>5.0.2</version>
</dependency>
with
<dependency>
<groupId>org.springframework.experimental</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>1.0.0-M3</version>
</dependency>
but now I am getting a null instead of a Page...
UPDATE 2
I've also tried the
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>11.1.0</version>
</dependency>
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>graphql-kickstart-spring-webflux</artifactId>
<version>11.1.0</version>
</dependency>
but got the same result. I figured it supports a CompletableFuture<List<Page>>, but this is still blocking and I've seen multiple tutorials on returning Mono/Flux from a graphql resolver...
UPDATE 3
I've updated the all the Spring modules' versions to 2.6.3 to be consistent and I've also removed the spring-boot-starter-web dependency, as the spring-boot-starter-webflux should be sufficient; but neither of those fixes have solved my issue.
UPDATE 4
This is the entity I want to return wrapped in a Flux:
#Document("pages")
public class Page {
#Id
private int id;
private String host;
private String path;
private String jobAnchorSelector;
private String jobLinkContains;
private int numberOfPages;
private int interval;
private Date lastScrapePerformed;
private String userUuid;
public Page() {
}
public Page(int id) {
this.id = id;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getJobAnchorSelector() {
return jobAnchorSelector;
}
public void setJobAnchorSelector(String jobAnchorSelector) {
this.jobAnchorSelector = jobAnchorSelector;
}
public String getJobLinkContains() {
return jobLinkContains;
}
public void setJobLinkContains(String jobLinkContains) {
this.jobLinkContains = jobLinkContains;
}
public int getNumberOfPages() {
return numberOfPages;
}
public void setNumberOfPages(int numberOfPages) {
this.numberOfPages = numberOfPages;
}
public String toString() {
return "Page [" + host + path + "]";
}
public int getInterval() {
return interval;
}
public void setInterval(int interval) {
this.interval = interval;
}
public Date getLastScrapePerformed() {
return lastScrapePerformed;
}
public void setLastScrapePerformed(Date lastScrapePerformed) {
this.lastScrapePerformed = lastScrapePerformed;
}
public String getUserUuid() {
return userUuid;
}
public void setUserUuid(String userUuid) {
this.userUuid = userUuid;
}
}
It's a MongoDB document and I'm using a ReactiveMongoRepository to fetch that, however for the sake of simplifying this issue I was trying to return just a Flux.just(new Page(2)).
First of all, if you're using Spring Boot, I would recommend that you use spring-boot-starter-graphql instead of graphql-spring-boot-starter, and you need to add spring-boot-starter-webflux to implement reactive data fetchers. Also if you want to return Flux, you should define returned type as an array in the schema (e.g. getPages: [Page!]!), otherwise, you should return Mono.
This will allow you to implement your query like this:
#Controller
public class PageController {
// ...
#QueryMapping
public Flux<Page> getPages() {
return pageService.getPages();
}
}
But you should note that by default Mono and Flux are adapted to a CompletableFuture where Flux values are aggregated and turned into a List. If you want to stream responses, then you should also use GraphQL subscription instead of a query.
I am using Spring Data Mongodb and Embeded mongoDB to persist the data.
Pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
</dependency>
applicaiton.properties
spring.data.mongodb.port=2019
spring.data.mongodb.database=testdb
spring.data.mongodb.host=localhost
Main class:
#SpringBootApplication
#EnableAutoConfiguration
#EnableMongoRepositories(basePackages = { "com.koka.mongotest.repo"})
public class MongotestApplication {
public static void main(String[] args) {
SpringApplication.run(MongotestApplication.class, args);
}
}
Enity or Domain class :
#Document
public class Person
{
#Indexed
private String personId;
private String name;
//getter and setters
}
Repo:
#Repository
public interface PersonRepo extends MongoRepository { //No Custom emthod}
Service layer :
#Service
public class ServiceImpl {
#Autowired
PresonRepo repo;
public void saveJon(Person p )
{
repo.save(p);
}
}
but Int DB its getting saved as
{"_id":{"$oid":"60e18f9d7eb50d70b56b543f"},"_class":"com.koka.mongotest.entity.Person"}
But that person Object hold info which is not being saved. Please advise on this,
Error creating bean with name 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaConfiguration': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception; nested exception is java.lang.IllegalStateException: Cannot load driver class: oracle.jdbc.driver.OracleDriver
pom.xml file
https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
</parent>
<groupId>com.Projectdashboardtool</groupId>
<artifactId>Project</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Project</name>
<description>Demo project for Spring Boot</description>
<properties>
<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-starter-jersey</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-web-services</artifactId>
</dependency> -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc8</artifactId>
<version>12.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
Controller class
#RestController
#RequestMapping("/project")
public class ProjectController {
#Autowired
private ProjectRepository projectRepository;
#GetMapping
public List<Project> list(){
//List<Project> project=new ArrayList<>();
return projectRepository.findAll();
}
#PostMapping
#ResponseStatus(HttpStatus.OK)
public void create(#RequestBody Project project) {
projectRepository.save(project);
}
#GetMapping("/{id}")
public Project get(#PathVariable("id") long id) {
return projectRepository.getOne(id);
}
}
Model class
package com.Projectdashboardtool.Project.Model;
import java.sql.Date;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
#Entity
#JsonIgnoreProperties({"hiberanateLazyInitializer", "handler"})
public class Project {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String dg_number;
private String project;
private String release_level;
private String release_area;
private String release_number;
#JsonFormat(shape=JsonFormat.Shape.STRING, pattern="dd-MM-yyyy")
private Date planned_release_date;
private Date release_date;
public String getDg_number() {
return dg_number;
}
public void setDg_number(String dg_number) {
this.dg_number = dg_number;
}
public String getProject() {
return project;
}
public void setProject(String project) {
this.project = project;
}
public String getRelease_level() {
return release_level;
}
public void setRelease_level(String release_level) {
this.release_level = release_level;
}
public String getRelease_area() {
return release_area;
}
public void setRelease_area(String release_area) {
this.release_area = release_area;
}
public String getRelease_number() {
return release_number;
}
public void setRelease_number(String release_number) {
this.release_number = release_number;
}
public Date getPlanned_release_date() {
return planned_release_date;
}
public void setPlanned_release_date(Date planned_release_date) {
this.planned_release_date = planned_release_date;
}
public Date getRelease_date() {
return release_date;
}
public void setRelease_date(Date release_date) {
this.release_date = release_date;
}
public String getRelease_type() {
return release_type;
}
public void setRelease_type(String release_type) {
this.release_type = release_type;
}
private String release_type;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Override
public String toString() {
return "Project [id=" + id + ", dg_number=" + dg_number + ", project=" + project + ", release_level="
+ release_level + ", release_area=" + release_area + ", release_number=" + release_number
+ ", planned_release_date=" + planned_release_date + ", release_date=" + release_date
+ ", release_type=" + release_type + "]";
}
}
application.properties file
spring.jpa.hibernate.ddl-auto=update
spring.jpa.database-platform=org.hibernate.dialect.SQLServer2012Dialect
spring.datasource.url=jdbc:oracle:thin:#//hostname/servicename
spring.datasource.username=username
spring.datasource.password=password
spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
Adding dependency :
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc8</artifactId>
<version>12.1.0</version>
</dependency>
And correct hibernate dialect - org.hibernate.dialect.OracleDialect should work.
I think you are using property file for DB oracle. From your exception i can able to see spring boot failed to load oracle driver. So download ojdbc6.jar from Oracle website or if you install oracle11g in your local system you can find ojdbc in jdbc/lib folder.
add this to your project, On eclipse right click on project --> build path --> add this jar.
So suppose you are using spring boot add this dependency to your pom.xml
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0</version>//add letest version
</dependency>
Suppose if your dependency not detected by maven follow the below steps:-
Run this command
mvn install:install-file - Dfile=C:\Users\user\.m2\repository\com\oracle\ojdbc6\11.2.0\ojdbc6.jar -DgroupId=com.oracle -DartifactId=ojdbc6 -Dversion=11.2.0 -Dpackaging=jar
Then You can Use this.
Oracle JDBC drivers are available on Central Maven. Check out this blog. You can add this GAV for 18.3 JDBC driver.
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>18.3.0.0</version>
I have just started springboot and tried to implement elastic search with spring-boot but I am getting this type of error while running spring-boot app
Consider defining a bean named 'elasticsearchTemplate' in your configuration.
POM.XML
<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-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>5.6.10</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
</dependencies>
Repository
#Repository
public interface StudentRepository extends ElasticsearchRepository<Student, Integer>{}
Controller
#RestController
public class Controller {
#Autowired
StudentRepository studentRepo;
#GetMapping(value="/student/all")
List<Student> getAllStudent() {
Iterator<Student> studentList = studentRepo.findAll().iterator();
List<Student> students = new ArrayList<>();
if(studentList.hasNext()) {
students.add(studentList.next());
}
return students;
}
#PostMapping(value="/student/add")
String addStudent(#RequestBody Student student) {
studentRepo.save(student);
return "Record Added Successfully";
}
#DeleteMapping(value="/student/delete/{id}")
String deleteStudent(#PathVariable int id) {
studentRepo.deleteById(id);
return "Record Deleted Successfully";
}
//#GetMapping(value="/student/findById/{id}")
}
Can Anyone help me to resolve this error
Consider defining a bean named 'elasticsearchTemplate' in your configuration.
You need to define some elastic search properties in your application.properties file such as cluster-nodes, cluster-names which are used by ElasticsearchTemplate and ElasticsearchRepository to connect to the Elasticsearch engine.
You can refer below mentioned link :
https://dzone.com/articles/elasticsearch-with-spring-boot-application
Note: Please refer to the spring-data-elasticsearch-versions or Spring Data Elasticsearch Changelog (check Elasticsearch version of desired release) to check version compatibility.
Solution(1):
If you want to use spring boot 1.x, simply create a #Configuration class and add a ElasticsearchOperations Bean. Please note than spring boot 1.x does not support the latest versions of ElasticSearch 5.x and higher.
cluster.name: make sure the cluster name you set in the code is the same as the cluster.name you set in $ES_HOME/config/elasticsearch.yml
#Configuration
public class ElasticSearchConfig {
#Bean
public ElasticsearchOperations elasticsearchTemplate() throws UnknownHostException {
return new ElasticsearchTemplate(getClient());
}
#Bean
public Client getClient() throws UnknownHostException {
Settings setting = Settings
.builder()
.put("client.transport.sniff", true)
.put("path.home", "/usr/share/elasticsearch") //elasticsearch home path
.put("cluster.name", "elasticsearch")
.build();
//please note that client port here is 9300 not 9200!
TransportClient client = new PreBuiltTransportClient(setting)
.addTransportAddress(new TransportAddress(InetAddress.getByName("127.0.0.1"), 9300));
return client;
}
}
Solution (2):Also, you can refer to this spring boot issue that shows automatic configuration of the Elasticsearch in the spring data from spring boot 2.2.0.
Therefore, using spring boot 2.2 and spring-boot-starter-elasticserach you don't need to configure the Elasticsearch manually.
Sample working project:
Versions:
spring boot : 2.2.0.RELEASE
Elasticsearch: 6.6.2
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>spring-boot-elasticsearch</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.0.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
application.properties:
spring.data.elasticsearch.cluster-name=elasticsearch
spring.data.elasticsearch.cluster-nodes=localhost:9300
spring.elasticsearch.jest.uris=http://localhost:9200
Main Application class:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Model class:
import lombok.*;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
#Document(indexName = "your_index", type = "books")
public class Book {
#Id
private String id;
private String title;
private String author;
private String releaseDate;
//getter, setter/constructors
}
Repository class:
import com.example.model.Book;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
#Repository
public interface BookRepository extends ElasticsearchRepository<Book, String> {
Page<Book> findByAuthor(String author, Pageable pageable);
List<Book> findByTitle(String title);
}
Service class:
some methods to test:
import com.example.model.Book;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import java.util.List;
public interface BookService {
Book save(Book book);
void delete(Book book);
Book findOne(String id);
Iterable<Book> findAll();
Page<Book> findByAuthor(String author, Pageable pageable);
List<Book> findByTitle(String title);
}
Service implementation:
import com.example.model.Book;
import com.example.repository.BookRepository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import java.util.List;
#Service
public class BookServiceImpl implements BookService {
private BookRepository bookRepository;
public BookServiceImpl(BookRepository bookRepository) {
this.bookRepository = bookRepository;
}
#Override
public Book save(Book book) {
return bookRepository.save(book);
}
#Override
public void delete(Book book) {
bookRepository.delete(book);
}
#Override
public Book findOne(String id) {
return bookRepository.findById(id).orElse(null);
}
#Override
public Iterable<Book> findAll() {
return bookRepository.findAll();
}
#Override
public Page<Book> findByAuthor(String author, Pageable pageable) {
return bookRepository.findByAuthor(author, pageable);
}
#Override
public List<Book> findByTitle(String title) {
return bookRepository.findByTitle(title);
}
}
Test class:
#RunWith(SpringRunner.class)
#SpringBootTest(classes = Application.class)
public class BookTest {
#Autowired
private BookService bookService;
#Autowired
private ElasticsearchTemplate esTemplate;
#Before
public void before(){
esTemplate.deleteIndex(Book.class);
esTemplate.createIndex(Book.class);
esTemplate.putMapping(Book.class);
esTemplate.refresh(Book.class);
}
#Test
public void testSave(){
Book book = new Book("1001", "Elasticsearch", "title", "23-FEB-2017");
Book testBook = bookService.save(book);
assertNotNull(testBook.getId());
assertEquals(testBook.getTitle(), book.getTitle());
assertEquals(testBook.getAuthor(), book.getAuthor());
assertEquals(testBook.getReleaseDate(), book.getReleaseDate());
}
}
I'm pretty new to Java, but I wanted to try to build a simple project with SpringMVC. It's just a simple CRUD app that should allow people to post notes.
When attempting to submit the form or query for notes, I get a null pointer exception when I attempt to call methods on JdbcTemplate. Here is the code for my application class:
package mvc;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.jdbc.core.JdbcTemplate;
#SpringBootApplication
public class SpringMvcApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(SpringMvcApplication.class, args);
}
#Autowired
JdbcTemplate jdbcTemplate;
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
public void run(String... string) throws Exception {
System.out.println("Creating tables");
jdbcTemplate.execute("drop table notes if exists");
jdbcTemplate.execute(("create table notes(" +
"id serial, content varchar(255), author varchar(255))"));
}
public static SpringMvcApplication instance = new SpringMvcApplication();
public static SpringMvcApplication getInstance() { return instance; }
}
Here is my NoteController.java:
package mvc;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
#Controller
public class NoteController {
#RequestMapping("/notes")
public String index() {
return "index";
}
#RequestMapping("/notes/new")
public String newNote(Model model) {
model.addAttribute("note",new Note());
return "new";
}
#RequestMapping(value="/notes", method= RequestMethod.POST)
public String create(Note note, Model model) {
model.addAttribute("note", note);
Note.create(note.getContent(), note.getAuthor());
return "show";
}
#RequestMapping(value = "/notes/{noteId}", method=RequestMethod.GET)
public String show(#PathVariable String noteId) {
long id = Long.parseLong(noteId);
Note note = Note.find(id);
return "show";
}
}
My Note model:
package mvc;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
public class Note {
private Long id;
private String content;
private String author;
public Note() {}
public Note(Long id, String content, String author) {
this.id = id;
this.content = content;
this.author = author;
}
public Long getId() {
return id;
}
public String getContent() {
return content;
}
public String getAuthor() {
return author;
}
public String toString() {
return content + "by " + author;
}
public static void create(String content, String author) {
JdbcTemplate jdbcTemplate = SpringMvcApplication.getInstance().getJdbcTemplate();
jdbcTemplate.update("INSERT INTO notes(content, author) values (?,?)", content, author);
}
public static Note find(Long id) {
JdbcTemplate jdbcTemplate = SpringMvcApplication.getInstance().getJdbcTemplate();
List<Note> notes = jdbcTemplate.query("SELECT id, content, author FROM notes WHERE id = ?", new Object[]{id},
new RowMapper<Note>() {
#Override
public Note mapRow(ResultSet rs, int rowNum) throws SQLException {
return new Note(rs.getLong("id"), rs.getString("content"),
rs.getString("author"));
}
});
return notes.get(0);
}
}
Here's my 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>org.test</groupId>
<artifactId>mvc</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Spring MVC</name>
<description>MVC Project for Ship It Saturday</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<start-class>mvc.SpringMvcApplication</start-class>
<java.version>1.7</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</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>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.4</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.2.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.3-1100-jdbc41</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
</dependencies>
I'm not really sure what the issue is with my code here. I was following a few different guides but most of them weren't too clear on what code was doing what. I'm sure there are probably some really obvious issues here, but I'm totally new to Spring and Java so I'm not seeing it.
EDIT:
Here is what I think are the relevant lines of the trace:
2015-04-11 19:01:35.125 ERROR 24895 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause
java.lang.NullPointerException: null
at mvc.Note.create(Note.java:44)
at mvc.NoteController.create(NoteController.java:30)
I should also mention that the run() method in the SpringMVCApplication class works just fine at creating the table, and if I move the insert and query statements into that method with static data the also work. It's only when I move them into their own methods so that I can use them dynamically that everything falls apart.
As already mentioned in the comments your SpringMvcApplication.getInstance() will not work as expected. You need something to connect the "spring-world" with the "not-spring-world". A possible solution would be to save the ApplicationContext as singleton.
#SpringBootApplication
public class SpringMvcApplication {
private static ApplicationContext context;
public static void main(String[] args) {
context = SpringApplication.run(SpringMvcApplication.class, args);
}
public static JdbcTemplate getJdbcTemplate() {
return context.getBean(JdbcTemplate.class);
}
}
Maybe you have to adapt it to your needs.