I have a POJO (the class has getters set for each field) which i am sending back to a variable in a different class where the template configuration is done. Somehow i am getting an error when the ftl tries to populate the view.
I don't know how to present an object of this type to a template: org.test.config.TransformerInfoBuilder. Here is the code where the error comes from:
[line 13, column 5 in templates/ConfigMain.ftl]
list TransformerInfoBuilders as TransformerInfoBuilder
Java error stacktrace:
freemarker.template.TemplateModelException: Don't know how to present an object of this type to a template: org.test.config.TransformerInfoBuilder
at freemarker.template.SimpleObjectWrapper.handleUnknownType(SimpleObjectWrapper.java:139)
at freemarker.template.SimpleObjectWrapper.wrap(SimpleObjectWrapper.java:116)
at freemarker.template.WrappingTemplateModel.wrap(WrappingTemplateModel.java:131)
at freemarker.template.SimpleSequence.get(SimpleSequence.java:197)
at freemarker.template.IteratorBlock$Context.runLoop(IteratorBlock.java:163)
at freemarker.template.Environment.visit(Environment.java:316)
at freemarker.template.IteratorBlock.accept(IteratorBlock.java:94)
at freemarker.template.Environment.visit(Environment.java:180)
at freemarker.template.IfBlock.accept(IfBlock.java:81)
at freemarker.template.Environment.visit(Environment.java:180)
at freemarker.template.MixedContent.accept(MixedContent.java:91)
at freemarker.template.Environment.visit(Environment.java:180)
at freemarker.template.Environment.process(Environment.java:166)
at freemarker.template.Template.process(Template.java:238)
at org.mule.config.ConfigLoader.main(ConfigLoader.java:116)
The ftl is as below.
<#if TransformerInfoBuilders?has_content>
<#list TransformerInfoBuilders as TransformerInfoBuilder>
<flow name="${TransformerInfoBuilder.id}">
</flow>
</#list>
<#else>
no content
</#if>
Java class for creating the object.
public class TransformerInfoBuilder {
String id="";
String name="";
String returnClass="";
String ignoreBadInput="";
String encoding="";
String mimeType="";
String templateName="";
public TransformerInfoBuilder(String id, String name,String returnClass, String encoding, String ignoreBadInput)
{
this.id=id;
this.name=name;
this.returnClass=returnClass;
this.encoding=encoding;
this.ignoreBadInput=ignoreBadInput;
}
public void setid(String id)
{
this.id=id;
}
public void setname(String name)
{
this.name=name;
}
public String getname()
{
return this.name;
}
public String getid()
{
return this.id;
}
public String getreturnClass()
{
return this.returnClass;
}
public String getignoreBadInput()
{
return this.ignoreBadInput;
}
public String getencoding()
{
return this.encoding;
}
}
Java class where the call to configurator is made:
public class ConfigLoader {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException, IOException {
Configuration cfg = new Configuration();
Template template = cfg.getTemplate("/templates/ConfigMain.ftl");
Connection dbconn=null;
Statement stmt=null;
ResultSet rs= null;
String id="";
HashMap<String,Map<String,String>> tinfo= new HashMap<String,Map<String,String>> ();
List<String> flowList = new ArrayList<String>();
List<TransformerInfoBuilder> TransformerInfoBuilders = new ArrayList<TransformerInfoBuilder>();
//Map<String,Object> flistfinal = new HashMap<String,Object>();
Map<String, Object> data = new HashMap<String, Object>();
List<Map<String,ArrayList<String>>> mapsfinal = new ArrayList<Map<String,ArrayList<String>>>();
try {
// Load the template
String configId =args[0];
System.out.println("+++++++++++++++++++++++configID is " + configId + " +++++++++++++++++++++++");
dbconn=DBConnection.connection();
System.out.println("\n\n++++++++++++++++++ Obtained DB connection ++++++++++++++++");
stmt = dbconn.createStatement();
System.out.println("\n\n++++++++++++++++++ Querying for Config Application Name ++++++++");
rs = stmt.executeQuery("SELECT * FROM FlowInfo where ConfigFileId =" + configId);
while (rs.next()) {
id = rs.getString("FlowID");
flowList.add(id);
}
TransformerInfoBuilders=Transformer.TransformerInfo(flowList);
data.put("TransformerInfoBuilders",TransformerInfoBuilders);
data.put("message","#[payload]");
Writer writer = new FileWriter("output/MainConfig.xml");
template.process(data, writer);
writer.flush();
writer.close();
//out.flush();
} catch (IOException e) {
e.printStackTrace();
} catch (TemplateException et) {
et.printStackTrace();
}finally {
try { if (rs != null) rs.close(); } catch (SQLException e) { e.printStackTrace(); }
try { if (stmt != null) stmt.close(); } catch (SQLException e) { e.printStackTrace(); }
try { if (dbconn != null) dbconn.close(); } catch (SQLException e) { e.printStackTrace(); }
}
}
}
Any pointers on what i might be doing wrong over here??
Thanks
Salim
After extending the DefaultObjectWrapper class the problem was solved. I had to upgrade it to a higher version of Freemarker.jar.
Related
I am storing an audio blob(recorded voice) in angular and then I am calling a spring boot API to store it in azure blob storage as so:
submit(){
const blob = this.audioRecording.getblob();
this.blobOutgoing = new FormData();
this.blobOutgoing.append('file', blob);
this.blobOutgoing.append('name', this.name);
this.blobOutgoing.append('email', this.email);
this.blobOutgoing.append('uid', this.uid);
this.pronunciationAPIService.saveEmployeeNameAlternate(this.blobOutgoing)
.subscribe((response: any) => {
console.log(response);
})
}
public void insertEmpoyeeRecord(Employee employee) {
try {
Statement stmt = getStatement();
System.out.println("Connected to the YugabyteDB Cluster successfully.");
// stmt.execute("DROP TABLE IF EXISTS employee");
/*stmt.execute("CREATE TABLE IF NOT EXISTS employee" +
" (id int primary key, name varchar, age int, language text)");*/
// System.out.println("Created table employee");
String insertStr = "INSERT INTO employees.employees VALUES ('"+employee.getUid()+"','"+employee.getEmail()+"','"+employee.getName()+"','"+employee.getUid()+"')";
String deleteStr = "DELETE FROM employees.employees WHERE email='"+employee.getEmail()+"' or uid='"+employee.getUid()+"'";
stmt.execute(deleteStr);
stmt.execute(insertStr);
----------> blobService.uploadFile(employee.getMultipartFile(), employee.getUid()); <----------------------------------
System.out.println("EXEC: " + insertStr);
ResultSet rs = stmt.executeQuery("select * from employees.employees");
while (rs.next()) {
System.out.println(String.format("Query returned: uid = %s, email = %s, name = %s, blob = %s",
rs.getString("uid"), rs.getString("email"), rs.getString("name"), rs.getString("audio")));
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void uploadFile(MultipartFile multipartFile, String audioFilenameRequest){
// String localFolderPath = "C:\\Users\\erman\\Downloads\\audiofolder\\";
try {
byte[] bytes = multipartFile.getBytes();
System.out.println("lenght:: " + bytes.length);
String audioFileName = audioFilenameRequest;
CloudBlobContainer containerReference = getCloudBlobContainer();
//Getting a blob reference
CloudBlockBlob blockBlobReference = containerReference.getBlockBlobReference(audioFileName);
//Creating blob and uploading file to it
//System.out.println("Uploading the sample file, Absolute path: "+sourceFile.getAbsolutePath() );
blockBlobReference.uploadFromByteArray(bytes,0,bytes.length);
System.out.println("upload to Azure cloud blob is done!!!!");
// blockBlobReference.upload
/* Path path = Paths.get(localFolderPath + multipartFile.getOriginalFilename());
Files.write(path,bytes);*/
} catch (IOException e) {
e.printStackTrace();
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (StorageException e) {
e.printStackTrace();
}
}
And then I try to retrieve from Angular by calling another Spring boot API:
playAudioFromBlob(){
this.pronunciationAPIService
.pronounceName(this.employee)
.subscribe((response: Array<Employee>) => {
console.log(response);
response.forEach( (employee) => {
let blob = new Blob(employee.blobByte, {type: "audio/webm"});
console.log(employee.blob);
const audioURL = URL.createObjectURL(blob);
let audio = new Audio(audioURL)
audio.controls = true;
audio.play();
})
});
}
public List<Employee> searchEmployeeByUid(String uid){
Employee employee = null;
try {
System.out.println("Connected to the YugabyteDB Cluster successfully.");
Statement stmt = getStatement();
String selectStr = "SELECT uid,email,name,audio FROM employees.employees WHERE uid='"+uid+"'";
stmt.execute(selectStr);
System.out.println("EXEC: " + selectStr);
ResultSet rs = stmt.executeQuery(selectStr);
while (rs.next()) {
employee = new Employee();
employee.setUid(rs.getString("uid"));
employee.setEmail(rs.getString("email"));
employee.setName(rs.getString("name"));
employee.setBlob(rs.getString("audio"));
}
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
byte[] blob = blobService.downloadFile(employee.getBlob());
employee.setBlobByte(blob);
return employee;
}
public byte[] downloadFile(String audioFileName) {
File downloadedFile = null;
byte[] audioByteArray = new byte[472179];
try {
// byte[] bytes = multipartFile.getBytes();
// String audioFileName = multipartFile.getOriginalFilename();
CloudBlobContainer containerReference = getCloudBlobContainer();
//Getting a blob reference
CloudBlockBlob blockBlobReference = containerReference.getBlockBlobReference(audioFileName);
// downloadedFile = new File(audioFileName);
//byte [] b = new byte[472179];
blockBlobReference.downloadToByteArray(audioByteArray,0);
System.out.println("download from Azure cloud blob is done!!!!:: Size : " + audioByteArray.length);
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (StorageException e) {
e.printStackTrace();
}
return audioByteArray;
}
public class Employee {
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getBlob() {
return blob;
}
public void setBlob(String blob) {
this.blob = blob;
}
public MultipartFile getMultipartFile() {
return blobOutgoing;
}
public void setMultipartFile(MultipartFile multipartFile) {
this.blobOutgoing = multipartFile;
}
private String name;
private String uid;
private String email;
private String blob;
private MultipartFile blobOutgoing;
public byte[] getBlobByte() {
return blobByte;
}
public void setBlobByte(byte[] blobByte) {
this.blobByte = blobByte;
}
private byte[] blobByte;
}
The problem is when converting the byte[] stream to a blob in angular I get the error:
Failed to construct 'Blob': The provided value cannot be converted to a sequence
I think I am getting this issue because I am not properly writing or reading the blob. I use ng-audio-recorder for the audio recordings in Angular. ng-audio-recorder builds the blob in audio webm
update: perhaps a more simplified question is how can you play back the byte[] stream in multipartfile in angular?
The initial argument (Parameter) must be presented in the sequence.
let blob = new Blob(employee.blobByte, {type: "audio/webm"}); console.log(employee.blob);
In place of this replace with the below one.
let blob=new Blob([employee.blobByte] ,{type: "audio/webm"}); console.log(employee.blob);
The controller code :
#GetMapping("/show/{id}")
public ResponseEntity<Student> findId(#PathVariable Student student) throws Exception {
Student showId = studentService.findId(student);
return new ResponseEntity<Student>(showId, HttpStatus.OK);
}
needs to return an object for a path id
Repository code:
public Student findId(Student student) throws Exception {
Connection connect = null;
Statement st = null;
ResultSet rec = null;
PreparedStatement pre = null;
List<Student> userlist = new ArrayList<Student>();
try {
Class.forName("com.mysql.cj.jdbc.Driver");
connect = DriverManager.getConnection("jdbc:mysql://localhost/mydatabase" +"?user=root&password=root&useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC");
connect.setAutoCommit(false);
st = connect.createStatement();
String sql = "SELECT * FROM student WHERE studentid = ? ";
pre = connect.prepareStatement(sql);
pre.setLong(1, student.getId());
pre.executeQuery();
} catch (Exception e) {
if (connect != null) {
try {
st.close();
connect.rollback();
} catch(SQLException e2) {
e2.printStackTrace();
}
}
} finally {
if (st != null) {
try {
st.close();
connect.setAutoCommit(true);
} catch(SQLException e) {
e.printStackTrace();
}
}
}
try {
connect.close();
} catch (SQLException e) {
e.printStackTrace();
}
return student;
}
ResultSet result = pre.executeQuery();
while (result.next()) {
long id = resultSet.getLong("studentId");
String name = resultSet.getString("name");
// another fields
return new Student(id, name);
}
And for controller if need only id (#PathVariable Long id) is more light.
Student response = studentService.findById(id);
return ResponseEntity.ok(response);
I connect to Hive and get id's of my data from row of table. Problems does not happens, when I connect to hive, send request and get response. But when i get id's from ResultSet i get an exception: org.apache.thrift.transport.TTransportException: SASL authentication not complete. Why does this exception arise and what needs to be done to avoid it? Sorry for my bad english.
It's my subsidiary class to create hive connection and send requests:
public class HiveDataSearcher implements AutoCloseable {
private static final String hiveDriverName = "org.apache.hive.jdbc.HiveDriver";
static {
try {
Class.forName(hiveDriverName);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
private Connection hiveConnection;
private String tableName;
private String whereBody;
public HiveDataSearcher(String url, String login, String password) {
try {
hiveConnection = DriverManager.getConnection(url, login, password);
} catch (SQLException e) {
throw new RuntimeException(e);
}
this.tableName = "";
this.whereBody = "";
}
public HiveDataSearcher(Connection hiveConnection) {
Objects.requireNonNull(hiveConnection, "hiveConnection");
this.hiveConnection = hiveConnection;
this.tableName = "";
this.whereBody = "";
}
public String getTableName() {
return tableName;
}
public HiveDataSearcher setTableName(String tableName) {
Objects.requireNonNull(tableName, "tableName");
this.tableName = tableName;
return this;
}
public String getWhereBody() {
return whereBody;
}
public HiveDataSearcher setWhereBody(String whereBody) {
Objects.requireNonNull(whereBody, "whereBody");
this.whereBody = whereBody;
return this;
}
public ResultSet select(String ... selectParams) {
return select(Arrays.asList(selectParams));
}
public ResultSet select(Iterable<String> selectParams) {
String request = prepareRequest(selectParams);
ResultSet response;
try {
response = hiveConnection
.createStatement()
.executeQuery(request);
} catch (SQLException e) {
throw new RuntimeException(e);
}
return response;
}
private String prepareRequest(Iterable<String> selectParams) {
return new StringBuilder()
.append("select").append(' ').append(selectParamsToHiveFormat(selectParams)).append(' ')
.append("from").append(' ').append(tableName).append(' ')
.append("where").append(' ').append(whereBody)
.toString();
}
private String selectParamsToHiveFormat(Iterable<String> selectParams) {
StringBuilder formattedSelectParams = new StringBuilder();
for (String selectedParam : selectParams) {
formattedSelectParams.append('\'').append(selectedParam).append('\'').append(',');
}
if (formattedSelectParams.length() == 0) {
formattedSelectParams.append('*');
} else {
formattedSelectParams.deleteCharAt(formattedSelectParams.length() - 1);
}
return formattedSelectParams.toString();
}
public void close() {
if (hiveConnection != null) {
try {
hiveConnection.close();
} catch (SQLException e) {
//nothing to do, just close connection
} finally {
hiveConnection = null;
}
}
}
}
This is the code in which i connect to hive:
private static final String HIVE_URL = <hive url>;
private static final String HIVE_LOGIN = <hive login>;
private static final String HIVE_PASSWORD = <hive password>;
private static final String[] SEARCH_FIELDS = new String[] {"rowkey"};
private List<String> getIdsFromHive(String tableName, String whereBody) {
ResultSet hiveResponse;
try (HiveDataSearcher searcher = new HiveDataSearcher(HIVE_URL, HIVE_LOGIN, HIVE_PASSWORD)) {
hiveResponse = searcher
.setTableName(tableName)
.setWhereBody(whereBody)
.select(SEARCH_FIELDS);
}
List<String> ids = new ArrayList<>();
try {
while (hiveResponse.next()) { // in this place throw TTransportException
ids.add(hiveResponse.getString(SEARCH_FIELDS[0]));
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
return ids;
}
In my case, the reason for this exception is closed the connection before closed the statement. So I suggest you to check whether you has maintain the connection correctly.
Here is my code, wish it will inspire you something:
Wrong code, close connection before closing the statement:
Connection connection = null;
Statement statement = null;
try {
connection = HIVEUTILS.getConnection();
statement = connection.createStatement();
statement.execute("DROP TABLE IF EXISTS tbl1");
statement.execute("CREATE TABLE `tbl1` (`id` int)");
statement.execute("INSERT INTO tbl1 VALUES(1)");
}finally {
if (connection != null){
connection.close();
}
if (statement != null){
statement.close(); // exception occur here.
}
}
The correct order of closing is: close resultSet(if any) -> close statement -> close connection.
Connection connection = null;
Statement statement = null;
try {
connection = HIVEUTILS.getConnection();
statement = connection.createStatement();
statement.execute("DROP TABLE IF EXISTS tbl1");
statement.execute("CREATE TABLE `tbl1` (`id` int)");
statement.execute("INSERT INTO tbl1 VALUES(1)");
}finally {
if (statement != null){
statement.close(); // change the order
}
if (connection != null){
connection.close();
}
}
So I'm working on a Ticketing System but for some reason I can't seem to get a location in my events.
The TicketingSystem class has some hashmaps where I add my data to.
It also has reader methods the one I'm having trouble with is readEvents().
public TicketSystem() {
queueService = new QueueService();
users = new HashMap<>();
locations = new HashMap<>();
events = new HashMap<>();
readData();
}
public void addLocation(Venue location) {
locations.put(location.getId(), location);
}
public void addEvent(Event event) {
events.put(event.getId(), event);
}
public static Event getEvent(String eventId) {
return events.get(eventId);
}
public static Venue getLocation(String locationId) {
return locations.get(locationId);
}
public void readLocations() {
try (BufferedReader reader = new BufferedReader(new FileReader("venuedata.txt"))) {
String line = "";
VenueMapper mapper = new VenueMapper();
while ((line = reader.readLine()) != null) {
Venue venue = mapper.map(line.split(";"));
locations.put(venue.getId(), venue);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void readEvents() {
try (BufferedReader reader = new BufferedReader(new FileReader("eventdata.txt"))) {
String line = "";
EventMapper mapper = new EventMapper();
while ((line = reader.readLine()) != null) {
Event event = mapper.map(line.split(";"));
events.put(event.getId(), event);
reader.readLine();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void readData() {
readEvents();
readLocations();
}
With an EventMapper class which reads data from a text file through the TicketingSystem class split by ";" data[5] is my locationId.
#Override
public Event map(String[] data) {
String dateAndTime = data[1];
StringBuilder date = new StringBuilder(dateAndTime.substring(0, 8));
StringBuilder time = new StringBuilder(dateAndTime.substring(8));
return new Event(data[0], data[2], date.toString(), time.toString(), data[3], Double.parseDouble(data[4]), data[5]);
}
}
This is my event class which contains the constructor I'm using returning the event in the EventMapper class
public Event(String id, String name, String date, String time, String description,
double price, String locationId) {
this(name, LocalDate.parse(date, DateTimeFormatter.ofPattern("ddMMyyyy")),
LocalTime.parse(time, DateTimeFormatter.ofPattern("HHmm")), description, price);
this.id = id;
*setLocation(TicketSystem.getLocation(locationId));*
}
public void setLocation(Venue location) {
this.location = location;
}
Everytime I debug there's data in the locations list but for some reason my events aren't picking up the locations I'm trying to get.
I'm having a problem using the BeanUtils.setProperty method.
I'm using this JAR:
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>
I run a MySQL query that returns one record and I'm mapping the resultset to a JavaBean that I've made.
Here you have the main class.
public class QueryTester {
public static void viewTable(Connection con) throws SQLException, InstantiationException, IllegalAccessException, InvocationTargetException {
Statement stmt = null;
String query = "SELECT * FROM Books WHERE code = 'AA00'";
try {
stmt = (Statement) con.createStatement();
ResultSet rs = stmt.executeQuery(query);
ResultSetMapper<Books> rsMapper = new ResultSetMapper<Books>();
List<Books> list = rsMapper.mapResultSetToObject(rs, Books.class);
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (stmt != null) {
stmt.close();
}
}
}
public static void main(String[] args) {
Connection conn = null;
String url = "jdbc:mysql://localhost/dbname";
String driver = "com.mysql.jdbc.Driver";
String userName = "root";
String password = "root";
try {
Class.forName(driver).newInstance();
conn = (Connection) DriverManager.getConnection(url,userName,password);
viewTable(conn);
conn.close();
} catch (Exception e) {
System.out.println("NO CONNECTION");
}
}
}
And this is the method that uses the BeanUtils.setProperty method.
public class ResultSetMapper<T> {
public List<T> mapResultSetToObject(ResultSet rs, Class<T> outputClass) throws InstantiationException, SQLException, IllegalAccessException, InvocationTargetException {
List<T> outputList = new ArrayList<T>();
if (rs == null) {
return outputList;
}
if (!outputClass.isAnnotationPresent(Entity.class)) {
throw new InstantiationException("Entity notation not present.");
}
ResultSetMetaData rsmd = rs.getMetaData();
// retrieve data fields from output class
Field[] fields = outputClass.getDeclaredFields();
while (rs.next()) {
T bean = (T) outputClass.newInstance();
for (int iterator = 0; iterator < rsmd.getColumnCount(); iterator++) {
String columnName = rsmd.getColumnName(iterator + 1);
Object columnValue = rs.getObject(iterator + 1);
for (Field field : fields) {
if (field.isAnnotationPresent(Column.class)) {
Column column = field.getAnnotation(Column.class);
if (column.name().equalsIgnoreCase(columnName) && columnValue != null) {
BeanUtils.setProperty(bean, field.getName(), columnValue);
break;
}
}
}
}
outputList.add(bean);
}
return outputList;
}
}
mapResultSetToObject method returns a List with one element that is correct but the bean is set in a wrong way.
The fields code and bookDescription are set right but kPrice field is set null instead of 3.000 that is the value from database.
I run this code in debug mode and "columnValue" variable's value is 3.000 but the setProperty method doesn't set the right value and the value remains null.
Here you have my Java Bean.
#Entity
public class Books {
#Column(name="code")
private String code;
#Column(name="book_description")
private String bookDescription;
#Column(name="kPrice")
private BigDecimal kPrice;
public Books() {}
public Books(String code, String bookDescription, BigDecimal kPrice){
this.code = code;
this.bookDescription = bookDescription;
this.kPrice = kPrice;
}
/* Getters and setters */
...
}
And this is the MySQL table and the record.
CREATE TABLE `Books` (
`code` varchar(4) NOT NULL,
`book_description` varchar(50) NOT NULL DEFAULT '',
`kPrice` decimal(10,4) NOT NULL DEFAULT '1.0000',
PRIMARY KEY (`code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
INSERT INTO dbname.Books (code, book_description, kPrice) VALUES('AA00', 'Description example', 3.0000);
Why I get this behaviour? What am I missing?
Thanks in advance
Are you sure which the name of setters/getters is the same of property?
In some case, the problem is that.
See my example below:
#Entity
public class Books {
#Column(name="code")
private String code;
#Column(name="book_description")
private String bookDescription;
#Column(name="kPrice")
private BigDecimal kPrice;
public Books() {}
public Books(String code, String bookDescription, BigDecimal kPrice){
this.code = code;
this.bookDescription = bookDescription;
this.kPrice = kPrice;
}
public void setKPrice ( Bigdecimal kPrice) // and not setkPrice or setPrice..
{
this.kPrice = kPrice;
}
public BigDecimal getKPrice () // and not getkPrice or getPrice..
{
return this.kPrice;
}
}