The Java Rest Api prints on http://localhost:8080/books
[{},{},{}]
instead of the booklist object. I use a main method a book_controller and a book model. Firstly I add a couple of books in the list in the method getbooks() and then I return them as a list.
Why does this happen?
application.java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
#SpringBootApplication (exclude = SecurityAutoConfiguration.class)
public class Lab6NosApplication {
public static void main(String[] args) {
SpringApplication.run(Lab6NosApplication.class, args);
}
}
Book_controller.java
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import ch.qos.logback.classic.Logger;
import net.minidev.json.JSONArray;
#Controller
public class Book_controller implements ErrorController, Serializable {
#GetMapping("books")
public #ResponseBody List<book> getbooks() {
List<book> bookList = new ArrayList<book>();
bookList.add(new book(1,"lokesh","gupta"));
bookList.add(new book(2,"lokesh","gupta"));
bookList.add(new book(3,"lokesh","gupta"));
java.lang.System.out.print(bookList);
return bookList;
}
#RequestMapping("/error")
#ResponseBody
public String handleError(HttpServletRequest request) {
Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
Exception exception = (Exception) request.getAttribute("javax.servlet.error.exception");
return String.format("<html><body><h2>Error Page</h2><div>Status code: <b>%s</b></div>"
+ "<div>Exception Message: <b>%s</b></div><body></html>",
statusCode, exception==null? "N/A": exception.getMessage());
}
#Override
public String getErrorPath() {
return "/error";
}
}
Book.java
public class Book {
public Book(Integer id, String title, String author) {
super();
this.id = id;
this.title = title;
this.author = author;
}
private Integer id;
private String title;
private String author;
//getters and setters
#Override
public String toString() {
return "Employee [id=" + id + ", title=" + title
+ ", author=" + author + "]";
}
}
Thank you!
You see it empty because your Book class doesn't have public getters or properties, so the serializer won't be able to access it's values.
Add getters to your Book class:
public Integer getId(){
return this.id;
}
public String getTitle(){
return this.title;
}
public String getAuthor(){
return this.author;
}
You can also improve your code, with better naming such as BookController instead of Book_controller. Have a look at java naming conventions.
Finally, take a look at a #RestController. If you use #RestController, you don't need to have #ResponseBody
Related
I am trying to create a CRUD application using Spring-boot and Mongo DB.
I am getting error the in the update and delete operations
During Delete, there is a timestamp error showing and on update a new object is getting created instead of updating the existing object. I have attached the controller and service layer codes.
Can anyone please find a solution for this.
Controller Layer
package com.springrest.springrest.controller;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.springrest.springrest.entities.Course;
import com.springrest.springrest.services.CourseService;
#CrossOrigin
#RestController
#RequestMapping("/api")
public class MyController {
#Autowired
private CourseService courseService;
#GetMapping("/courses")
public ResponseEntity<?> getCourses(){
return ResponseEntity.ok(this.courseService.GetCourses());
}
#PostMapping("/courses")
public ResponseEntity<?> addCourse(#RequestBody Course course)
{
Course save=this.courseService.addCourse(course);
return ResponseEntity.ok(save);
}
#GetMapping("/courses/{courseId}")
public ResponseEntity<?> getCourse(#PathVariable String courseId ){
Optional<Course> save=this.courseService.getCourse(Integer.parseInt(courseId));
return ResponseEntity.ok(save);
}
#PutMapping("/courses/{courseId}")
public ResponseEntity<?> updateCourse(#PathVariable String courseId,
#RequestBody Course course)
{
Optional<Course> save=Optional.ofNullable(this.courseService.updateCourse(Integer.parseInt
(courseId),course));
return ResponseEntity.ok(save);
}
#DeleteMapping("/courses/{courseId}")
public void deleteCourse(#PathVariable String courseId)
{
this.courseService.deleteCourse(Integer.parseInt(courseId));
//return ResponseEntity.ok(this.courseService.deleteCourse(Integer.parseInt(courseId)));
}
}
Service Layer
package com.springrest.springrest.services;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.springrest.springrest.entities.Course;
import com.springrest.springrest.repository.CourseRepository;
#Service
public class CourseServiceimpl implements CourseService
{
#Autowired
private CourseRepository userlist;
public List<Course> GetCourses() {
return this.userlist.findAll();
}
public Course addCourse(Course course) {
return this.userlist.save(course);
}
public Optional<Course> getCourse(int courseId)
{
Optional<Course> c=this.userlist.findById(courseId);
return c;
}
#Override
public Course updateCourse(int courseId, Course course)
{
Course c=this.userlist.findById(courseId).get();
c.setId(course.getId());
c.setTitle(course.getTitle());
c.setDescription(course.getDescription());
return this.userlist.save(c);
}
#Override
public void deleteCourse(int courseId)
{
//Course c= this.userlist.findById(courseId).get();
this.userlist.deleteById(courseId);
}
}
Entity Layer
package com.springrest.springrest.entities;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;
#Document(collection="Course")
public class Course {
#Field( name="id")
private int id;
#Field(name="title")
private String title;
#Field(name="description")
private String description;
public Course(int id, String title, String description) {
super();
this.id = id;
this.title = title;
this.description = description;
}
public Course() {
super();
}
#Override
public String toString() {
return "Course [id=" + id + ", title=" + title + ", description=" + description + "]";
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
This is the error I am getting on a Delete Request
{
"timestamp": "2022-11-09T18:45:58.630+00:00",
"status": 500,
"error": "Internal Server Error",
"path": "/api/courses/147"
}
Are you getting an error in get and save operations? Because although you inject CourseService in controller, you did not override get and save operations methods in CourseServiceimpl class.
I am new to spring boot and i am creating a spring boot app to generate csv files from data fetched from database .I'm using h2 database for it and want to get selective columns from my entity-id,amount
entity class:
package com.reports.entities;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity(name="reportDetails")
#Table(name = "reports")
public class Report {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="id")
private long id;
#Column(name="name")
private String name;
#Column(name="email")
private String email;
#Column(name="amount")
private int amount;
public Report() {
super();
}
public Report(int id, String name, String email, int amount) {
super();
this.id = id;
this.name = name;
this.email = email;
this.amount = amount;
}
public long getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
}
main class:
package com.reports;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.reports.entities.Report;
import com.reports.repository.ReportsRepository;
#SpringBootApplication
public class ExportCsvApplication implements CommandLineRunner {
#Autowired
ReportsRepository reportsRepository;
public static void main(String[] args) {
SpringApplication.run(ExportCsvApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
List<Report> reports = new ArrayList<>();
// create dummy employees
reports.add(new Report(1,"roy","roy#123.com",2500));
reports.add(new Report(2,"joy","joy#123.com",2500));
reports.add(new Report(3,"soy","soy#123.com",2500));
reports.add(new Report(4,"moy","moy#123.com",2500));
reports.add(new Report(5,"noy","noy#123.com",2500));
reportsRepository.saveAll(reports);
}
}
repository :
package com.reports.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.reports.entities.IReport;
import com.reports.entities.Report;
#Repository("reportsRepository")
public interface ReportsRepository extends JpaRepository<Report,Long>{
}
Service class:
package com.reports.services;
import java.util.List;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.reports.entities.IReport;
import com.reports.entities.Report;
import com.reports.repository.ReportsRepository;
#Transactional
#Service
public class ReportsService {
#Autowired
ReportsRepository reportsRepository;
public List<Report> fetchAll() {
return (List<Report>) reportsRepository.findAll();
}
}
Controller:
package com.reports.controllers;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.opencsv.CSVWriter;
import com.opencsv.bean.StatefulBeanToCsv;
import com.opencsv.bean.StatefulBeanToCsvBuilder;
import com.reports.entities.Report;
import com.reports.services.ReportsService;
#RestController
public class ReportsController {
#Autowired
ReportsService reportsService;
#GetMapping("/export-report")
public void exportCSV(HttpServletResponse response) throws Exception {
// set file name and content type
String filename = "details.csv";
response.setContentType("text/csv");
response.setHeader(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"" + filename + "\"");
// create a csv writer
StatefulBeanToCsv<Report> writer = new StatefulBeanToCsvBuilder<Report>(response.getWriter()).withQuotechar(CSVWriter.NO_QUOTE_CHARACTER).withSeparator(CSVWriter.DEFAULT_SEPARATOR).withOrderedResults(false).build();
// write all employees to csv file
writer.write(reportsService.fetchAll());
}
}
I want to know what would be the best method to incorporate for it i tried query but faced errors.Please let me know how do i get this done
This is more of being related to the opencsv library than Spring or Spring Boot itself.
When constructing the StatefullBeanToCsvBuilder, you should use the withIgonreField builder property to instruct the final StatefullBeanToCsv on which fields to ignore for which types.
Say you want only the id and amount fields out of your Report entity, you can achieve this as follows:
#RestController
public class ReportsController {
#Autowired
ReportsService reportsService;
#GetMapping("/export-report")
public void exportCSV(HttpServletResponse response) throws Exception {
// set file name and content type
String filename = "details.csv";
response.setContentType("text/csv");
response.setHeader(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"" + filename + "\"");
// Configure the CSV writer builder
StatefulBeanToCsvBuilder<Report> builder = new StatefulBeanToCsvBuilder<Report>(response.getWriter()).withQuotechar(CSVWriter.NO_QUOTE_CHARACTER).withSeparator(CSVWriter.DEFAULT_SEPARATOR).withOrderedResults(false);
// Ignore any field except the `id` and `amount` ones
Arrays.stream(Report.class.getDeclaredFields())
.filter(field -> !("id".equals(field.getName()) || "amount".equals(field.getName())))
.forEach(field -> builder.withIgnoreField(Report.class, field));
// create a csv writer
StatefulBeanToCsv<Report> writer = builder.build();
// write all employees to csv file
writer.write(reportsService.fetchAll());
}
}
Note: This is a project which has a connection with database on other tables. I just made a new table, but i must have something wrong in my codes, because i cant get what i want.
I have a City table, and this table has 3 columns, named id, name, city_id. And i imported a csv file, so when i query, I can see some data.
I wrote Entity, Repository, Controller, and Service, in Java on Eclipse
What should I do? For example, when i search like localhost:8181/mfc/city/getAllCities that should give me all the cities as json
Could you tell me what i should add?
City.java
package com.mfc.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="city")
public class City{
#Id
#Column(name="id")
#GeneratedValue(strategy=GenerationType.IDENTITY)
int id;
#Column(name="city_name")
String cityName;
#Column(name="city_id")
int cityId;
public City() {
super();
}
public City(int id, String cityName, int cityId) {
super();
this.id = id;
this.cityName = cityName;
this.cityId = cityId;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCityName() {
return cityName;
}
public void setCityName(String cityName) {
this.cityName = cityName;
}
public int getCityId() {
return cityId;
}
public void setCityId(int cityId) {
this.cityId = cityId;
}
}
CityController.java
package com.mfc.admin.controller;
import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.mfc.admin.service.CityService;
import com.mfc.entity.City;
#RestController
#RequestMapping("/city")
public class CityController {
private static final Logger logger = LogManager.getLogger(CityController.class);
#Autowired
CityService cityService;
#RequestMapping(value="/getAllCities", method=RequestMethod.GET, headers = "Accept=application/json")
public List getCities() {
logger.trace("CityController: getAllCities begins");
List listOfCities = cityService.getAllCities();
logger.trace("CityController: getAllCities ends");
return listOfCities;
}
#RequestMapping(value="/getCity/{id}", method=RequestMethod.GET, headers = "Accept=application/json")
public City getCityById(#PathVariable int id) {
return cityService.getCity(id);
}
}
CityService.java
package com.mfc.admin.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.mfc.entity.City;
import com.mfc.repository.CityRepository;
#Service("cityService")
public class CityService {
#Autowired
CityRepository cityDTO;
#Transactional
public List getAllCities() {
return cityDTO.getAllCities();
}
#Transactional
public City getCity(int id) {
return cityDTO.getCity(id); // getCity is red here, there is mistake i guess
}
}
CityRepository.java
package com.mfc.repository;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import com.mfc.entity.City;
public interface CityRepository extends JpaRepository<City, Integer>{
List getAllCities();
City getCity();
}
In the CityService you call the CityRepository like this
return cityDTO.getCity(id); // getCity is red here, there is mistake i guess
But no such method is defined in the CityRepository. Try using this line return cityDTO.findById(id).get();
You can't see the method findById(Integer id) in the CityRepository, but it is there, because the CityRepository extends JpaRepository<City, Integer>. Find some Spring Data tutorial to know what's really going on in here, long story short the Spring Data is able to generate a lot of standard methods for you.
The method cityDTO.findById(id) returns Optional<City>, not City. To get the instance of City, just add '.get()' method, as it is in the example. It should work for you if city exists in the database. For proper work with Optional find some tutorial. It is a wrapper of an object that may or may not be present, detailed explanation is out of the scope of this answer.
maybe you can try to set up message converter manualy, google MappingJackson2HttpMessageConverter and you'll know what to do.
I have following model class:
package com.restAPIExmaple;
public class ApiModel {
private String City;
private String TeamName;
private String QBName;
public ApiModel() {
}
public ApiModel(String city, String teamName, String qBName) {
City = city;
TeamName = teamName;
QBName = qBName;
}
public String getCity() {
return City;
}
public void setCity(String city) {
City = city;
}
public String getTeamName() {
return TeamName;
}
public void setTeamName(String teamName) {
TeamName = teamName;
}
public String getQBName() {
return QBName;
}
public void setQBName(String qBName) {
QBName = qBName;
}
}
Here is the service class:
package com.restAPIExmaple;
import java.util.List;
import org.springframework.stereotype.Service;
import java.util.Arrays;
#Service
public class ApiService {
private List <ApiModel> score = Arrays.asList(
new ApiModel("Jacksonville","Jaguars","Gardner Minshew"),
new ApiModel("Tempa Bay", "Buccaneer", "Tom Brady"),
new ApiModel("San Fran", "49rs", "Jimmy Garoppolo"),
);
public List<ApiModel> getScores()
{
return score;
}
public ApiModel getTeam(String team){
return score.stream().filter(t -> t.getTeamName().equalsIgnoreCase(team)).findFirst().get();
}
}
The Controller is as below:
package com.restAPIExmaple;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
#RestController
#RequestMapping("/football")
public class ApiController {
#Autowired
private ApiService apiService;
#GetMapping(value = "/scores", produces = {MediaType.APPLICATION_XML_VALUE,
MediaType.APPLICATION_JSON_VALUE})
public List<ApiModel> getScores(){
return apiService.getScores();
}
#GetMapping(value="/{team}", produces = {MediaType.APPLICATION_XML_VALUE,
MediaType.APPLICATION_JSON_VALUE})
public ApiModel getTeam(#PathVariable String team){
return apiService.getTeam(team);
}
}
Here is the response in xml:
<List>
<item>
<teamName>Jaguars</teamName>
<city>Jacksonville</city>
<qbname>Gardner Minshew</qbname>
</item>
<item>
<teamName>Buccaneer</teamName>
<city>Tempa Bay</city>
<qbname>Tom Brady</qbname>
</item>
<item>
<teamName>49rs</teamName>
<city>San Fran</city>
<qbname>Jimmy Garoppolo</qbname>
</item>
</List>
Problem: The order of the object properties has been changed in the out put. I cant get City, Team name , QBname in that order order in the response. When I generate getter and setter using Eclipse, the order of the fields there is different from the model class as well. Any idea? Thank you.
start variable name with simple letters. that's the case
The springboot application exposes the graphql API on the endpoint "localhost:8091/rest/books". When I test it with Postman passing the query in the body as graphQL type it gives error "Invalid Syntax", whereas when I pass the same query as raw text, it yields correct results. I'm using HSQL. The structure of my application is:
The files with their code respectively are:
Book.java
package com.techprimers.graphql.springbootgrapqlexample.model;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
//#AllArgsConstructor
//#NoArgsConstructor
#Setter
#Getter
#Table
#Entity
public class Book {
#Id
private String isn;
public Book() {
super();
}
public Book(String isn, String title, String publisher, String[] authors, String publishedDate) {
super();
this.isn = isn;
this.title = title;
this.publisher = publisher;
this.authors = authors;
this.publishedDate = publishedDate;
}
public String getIsn() {
return isn;
}
public void setIsn(String isn) {
this.isn = isn;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getPublisher() {
return publisher;
}
public void setPublisher(String publisher) {
this.publisher = publisher;
}
public String[] getAuthors() {
return authors;
}
public void setAuthors(String[] authors) {
this.authors = authors;
}
public String getPublishedDate() {
return publishedDate;
}
public void setPublishedDate(String publishedDate) {
this.publishedDate = publishedDate;
}
private String title;
private String publisher;
private String[] authors;
private String publishedDate;
}
BookRepository.java
package com.techprimers.graphql.springbootgrapqlexample.repository;
import com.techprimers.graphql.springbootgrapqlexample.model.Book;
import org.springframework.data.jpa.repository.JpaRepository;
public interface BookRepository extends JpaRepository<Book, String> {
}
BookResource.java
package com.techprimers.graphql.springbootgrapqlexample.resource;
import com.techprimers.graphql.springbootgrapqlexample.service.GraphQLService;
import graphql.ExecutionResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#CrossOrigin(origins = "http://localhost:3000")
#RequestMapping("/rest/books")
#RestController
public class BookResource {
#Autowired
GraphQLService graphQLService;
#PostMapping
public ResponseEntity<Object> getAllBooks(#RequestBody String query) {
ExecutionResult execute = graphQLService.getGraphQL().execute(query);
return new ResponseEntity<>(execute, HttpStatus.OK);
}
}
AllBooksDataFetcher.java
package com.techprimers.graphql.springbootgrapqlexample.service.datafetcher;
import com.techprimers.graphql.springbootgrapqlexample.model.Book;
import com.techprimers.graphql.springbootgrapqlexample.repository.BookRepository;
import graphql.schema.DataFetcher;
import graphql.schema.DataFetchingEnvironment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
#Component
public class AllBooksDataFetcher implements DataFetcher<List<Book>>{
#Autowired
BookRepository bookRepository;
#Override
public List<Book> get(DataFetchingEnvironment dataFetchingEnvironment) {
return bookRepository.findAll();
}
}
BookDataFetcher.java
package com.techprimers.graphql.springbootgrapqlexample.service.datafetcher;
import com.techprimers.graphql.springbootgrapqlexample.model.Book;
import com.techprimers.graphql.springbootgrapqlexample.repository.BookRepository;
import graphql.schema.DataFetcher;
import graphql.schema.DataFetchingEnvironment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
#Component
public class BookDataFetcher implements DataFetcher<Book>{
#Autowired
BookRepository bookRepository;
#Override
public Book get(DataFetchingEnvironment dataFetchingEnvironment) {
String isn = dataFetchingEnvironment.getArgument("id");
return bookRepository.findById(isn).get();
}
}
And in the resources folder is
Books.graphql (contains schema)
schema {
query: Query
}
type Query {
allBooks: [Book]
book(id: String): Book
}
type Book {
isn: String
title: String
publisher: String
authors: [String]
publishedDate: String
}