How to fix JsonProperty issue in springboot model class - spring

I am trying to change the attribute name to snake_case for the response in a model class. The Jsonproperty works fine with DB entity class, but not with the model class which does not have any DB entity mapped.
sample code which is not working.
SubtestResult.java -- Modelclass
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
public class SubtestResult {
#JsonProperty("expected_value") #Getter #Setter private String expectedValue;
#JsonProperty("actual_value") #Getter #Setter private List<String> actualValue;
}
Assertion.java
public class assertion {
private SubtestResult calculate(string actualValue){
SubtestResult subtestResult = new SubtestResult();
subtestResult.setActualValue(actualValue);
subtestResult.setExpectedValue("true");
}
Actual result
{
"expectedValue": true
"actualValue": false
}
Expected :
{
"expected_value": true
"actual_value": false
}
Note: There is no DTO entity for this. this entire model object gets stored as a string.

Related

Getting null value in h2 database when using spring boot

I am trying to insert data into the h2 database taking input from user.But primary key is getting inserted but the other is stored as null.
Here is my application.properties
spring.sql.init.platform==h2
spring.datasource.url=jdbc:h2:mem:preethi
spring.jpa.defer-datasource-initialization: true
spring.jpa.hibernate.ddl-auto=update
Here is Controller class AlienController.java
package com.preethi.springbootjpa.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.preethi.springbootjpa.model.Alien;
import com.preethi.springbootjpa.repo.AlienRepo;
#Controller
public class AlienController {
#Autowired
AlienRepo repo;
#RequestMapping("/")
public String home()
{
return "home.jsp";
}
#RequestMapping("/addAlien")
public String addAlien( Alien alien)
{
repo.save(alien);
return "home.jsp";
}
}
Here is Alien.java
package com.preethi.springbootjpa.model;
import javax.persistence.Entity;
import javax.persistence.Id;
import org.springframework.stereotype.Component;
#Component
#Entity
public class Alien {
#Id
private int aid;
private String aname;
public Alien()
{
}
public Alien(int aid, String aname) {
super();
this.aid = aid;
this.aname = aname;
}
public int getAid() {
return aid;
}
public void setAid(int aid) {
this.aid = aid;
}
public String getName() {
return aname;
}
public void setName(String name) {
this.aname = name;
}
#Override
public String toString() {
return "Alien [aid=" + aid + ", name=" + aname + "]";
}
}
Here is AlienRepo.java
package com.preethi.springbootjpa.repo;
import org.springframework.data.repository.CrudRepository;
import com.preethi.springbootjpa.model.Alien;
public interface AlienRepo extends CrudRepository<Alien,Integer>{
}
Here is data.sql;
insert into alien values(101,'Preethi');
when I try to insert data from data.sql,it is getting inserted but when I try to insert data taking input from user, data is stored as null(except primary key).
Here is the table :
table
I got the same issue when i forgot to add the gettters and setters for an entity class.
Finally solved it, there is no problem with the code...It's just all the configuraton things that messed up.
Just did everything from scratch and took care of build path and configurations.
Solved..

Handle Ambiguous handler methods mapped convention

I have 2 GET endpoints for Chemical resource:
In the first endpoint, I want the chemical object by id, which is unique through every chemical.
#GetMapping("/chemical/{id}")
In the second GET endpoint, I want all the chemicals which are correspond to a specific lab (lab is mandatory).
#GetMapping("/chemical/{labKey}")
Spring cannot distinguish between /chemical/myLab and /chemical/12, I can understand this. I know I should change the endpoint mapping, but how? Can someone suggest a good convention for this specific case? eg. #GetMapping("/chemical/{labKey}/{id}" seems redundant for me, since I don't use labKey pathVariable, I will only need id, I will call something like this: chemicalService.findById(id).
I think the best way to do this is by using two end points:
/chemical/{id} which will fetch your chemical by identifier using #GetMapping("/chemicals/{id}").
The second would use a query param labKey to filter based on the lab key. This will have a generic #GetMapping("/chemicals"). chemicals?labKey=lab1 would be the URI.
Below is my implementation.
Controller class
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
#Service
public class ChemicalService {
private List<ChemicalDTO> chemicals = Arrays.asList(
new ChemicalDTO(1L, "chem1", "lab1"),
new ChemicalDTO(2L, "chem2", "lab2"),
new ChemicalDTO(3L, "chem3", "lab1"),
new ChemicalDTO(4L, "chem4", "lab3")
);
public Optional<ChemicalDTO> getChemicalById(Long id) {
return chemicals.stream().filter(e -> e.getId().equals(id)).findAny();
}
public List<ChemicalDTO> getChemicalByLabKey(String labKey) {
if( labKey.isBlank() || labKey.isEmpty() ) return new ArrayList<>();
return chemicals
.stream()
.filter(e -> e.getLabKey().equals(labKey))
.collect(Collectors.toList());
}
}
Service class
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
#Service
public class ChemicalService {
private List<ChemicalDTO> chemicals = Arrays.asList(
new ChemicalDTO(1L, "chem1", "lab1"),
new ChemicalDTO(2L, "chem2", "lab2"),
new ChemicalDTO(3L, "chem3", "lab1"),
new ChemicalDTO(4L, "chem4", "lab3")
);
public Optional<ChemicalDTO> getChemicalById(Long id) {
return chemicals.stream().filter(e -> e.getId().equals(id)).findAny();
}
public List<ChemicalDTO> getChemicalByLabKey(String labKey) {
if( labKey.isBlank() || labKey.isEmpty() ) return new ArrayList<>();
return chemicals
.stream()
.filter(e -> e.getLabKey().equals(labKey))
.collect(Collectors.toList());
}
}
DTO class
import lombok.AllArgsConstructor;
import lombok.Data;
#Data
#AllArgsConstructor
public class ChemicalDTO {
private Long id;
private String name;
private String labKey;
}
You can find more information in the REST resource naming conventions and examples here
If the path is the same and the number of path variables is also the same, below would be the clean approach to handle this situation.
you can consider below code snippet
#GetMapping(value = "/chemical", params = "id")
public String getChemicalById(#RequestParam(value = "id") String id) {
return "ID method: "+id;
}
#GetMapping(value = "/chemical", params = "label")
public String getChemicalByLabel(#RequestParam(value = "label") String label) {
return "Label method: "+label;
}
The URLs are as follows:
/chemical?id=ID
/chemical?label=LABEL

How can I capture a value that comes through POST to execute a procedure stored in Spring Boot

I am working with Spring Boot, in which I am relatively new, and in this case I am doing a database validation through a Stored Procedue, which I could already solve, the reality is that until now I had done the tests sent the parameter of entry (a mobile number) by GET, but it is required for project reasons, send the parameter through POST, that is to say in a Body with the method:
Method Get
With a Body using the POST Method:
Request
{
"movil":"04242374781";
}
Reponse:
{
"result": "Cliente no encontrado",
"code": "NA22003"
}
mobile is an attribute of the database where the Stored Procedure is executed, for this case it is only necessary to pass that parameter to execute the SP, which returns a response that is not the same object of the database in which it is mobile, then you will see it in the code.
I understand that you can send the parameter for consultation with POST, but in my case try to guide me according to what I got on the internet, but I got an error:
Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'text/plain' not supported]
My Code
Main class
package com.app.validacion;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
My controller
package com.app.validacion.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import com.app.validacion.dao.DriverBonificadosRepository;
import com.app.validacion.entity.RespuestaVo;
#RestController
public class DriverBonificadosController {
#Autowired // Inyeccion de Dependecia, en este caso del Respository
private DriverBonificadosRepository dao;
#GetMapping("/service/{movil}")
public RespuestaVo ConsultarMovil(#PathVariable("movil") String movil) {
System.out.println(movil);
return dao.validarClienteBonifiado(movil);
}
/*
the code I was trying to use to send a request in JSON and try to get the mobile parameter,but
I got an error:
Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type
'text/plain' not supported]
/*
* #PostMapping(value = "/service",consumes = "application/json", produces="application/json")
* public RespuestaVo ValidateClient(#RequestBody DriverBonificados driver) {
* System.out.println(driver.getMovil());
* return dao.validarClienteBonifiado(driver.getMovil());
} */
}
My Repository
package com.app.validacion.dao;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import com.app.validacion.entity.DriverBonificados;
import com.app.validacion.entity.RespuestaVo;
#Repository
public interface DriverBonificadosRepository extends JpaRepository<DriverBonificados, Integer> {
#Query(nativeQuery = true,value = "call ValidacionClienteBonificado(:movil)")
RespuestaVo validarClienteBonifiado(#Param("movil") String pMovil);
}
My Entity
package com.app.validacion.entity;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="DriveBonificados")
public class DriverBonificados {
#Id
private int id;
private String movil;
private String contador;
private Date fecha_driver;
private Date fecha_alta;
private Date fecha_fin;
private Date codigo_transaccion;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getMovil() {
return movil;
}
public void setMovil(String movil) {
this.movil = movil;
}
public String getContador() {
return contador;
}
public void setContador(String contador) {
this.contador = contador;
}
public Date getFecha_driver() {
return fecha_driver;
}
public void setFecha_driver(Date fecha_driver) {
this.fecha_driver = fecha_driver;
}
public Date getFecha_alta() {
return fecha_alta;
}
public void setFecha_alta(Date fecha_alta) {
this.fecha_alta = fecha_alta;
}
public Date getFecha_fin() {
return fecha_fin;
}
public void setFecha_fin(Date fecha_fin) {
this.fecha_fin = fecha_fin;
}
public Date getCodigo_transaccion() {
return codigo_transaccion;
}
public void setCodigo_transaccion(Date codigo_transaccion) {
this.codigo_transaccion = codigo_transaccion;
}
}
My Model Response
package com.app.validacion.entity;
public interface RespuestaVo {
String getCode();
String getResult();
}
Nice post, but the (first encountered problem) solution is trivial:
With:
Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'text/plain' not supported]
and with this postman request, You need to:
postman specific: switch the (request>body) content type from "Text" to "JSON (application/json)"
generally: add a (http) header to Your request like
Content-Type: application/json;...

Unexpected and unwanted div element in return from Spring RestController

I return an object instance of the following class from a Spring RestController method.
package x
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
#XmlRootElement(name = "invoices")
public class Invoices implements Serializable {
private Info info;
private Set<Customer> customers = new HashSet<>();
private List<Invoice> invoices = new ArrayList<>();
public Info getInfo() {
return info;
}
public void setInfo(Info info) {
this.info = info;
}
#XmlElement(name = "customer")
public Set<Customer> getCustomers() {
return customers;
}
public void setCustomers(Set<Customer> customers) {
this.customers = customers;
}
#XmlElement(name = "invoice")
public List<Invoice> getInvoices() {
return invoices;
}
public void setInvoices(List<Invoice> invoices) {
this.invoices = invoices;
}
}
The Controller method has the signature;
#RequestMapping(value = "/invoice", method = RequestMethod.GET, produces = "application/xml; charset=UTF-8")
This returns an XML with an unexpected div element and an attribute named slick_uniqueid on the top element. How do I get rid of this, and where does this come from?
<invoices slick-uniqueid="3">
<div>
<a id="slick_uniqueid" />
</div>
I found the answer to this myself. The raw response from the server does not include this attribute, nor the extra element. It's chrome that modifies the XML slightly when it displays it in-browser. The attribute and element is not there if I do a 'view source' either. Strange. I have never noticed that before

Spring Test DBUnit: Unable to load dataset from file

I'm trying to use Spring Test DBUnit for running an integration test that checks if a DAO's services are running correctly. For two similar entities, I was able to create tests that run OK, but for this particular entity, the test can't run properly.
The test will be ignored, and the only Exception I will see in the console is:
java.lang.IllegalArgumentException: Unable to load dataset from "data/offline_message.xml" using class com.github.springtestdbunit.dataset.FlatXmlDataSetLoader
Here are the relevant files. XML file:
<dataset>
<mp_account id="1" auth_hash="ted.mosby" first_name="Ted" last_name="Mosby" credential="EMAIL" transport_session="someTransportSession"/>
<mp_account id="2" auth_hash="lily.aldrin" first_name="Lily" last_name="Aldrin" credential="MEH" transport_session="someTransportSession"/>
<mp_message id="1" recipient_account_id="1" sender_account_id="2"/>
</dataset>
Test class that is failing:
import com.github.springtestdbunit.annotation.DatabaseSetup;
import com.somecompany.messaging.domain.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import java.util.Date;
import java.util.List;
#DatabaseSetup("data/message.xml")
public class MessageDaoTest extends AbstractDaoTest<Message> {
private static final Long ACCOUNT_ID = 1L;
public static final long DATE_LONG = 1431018764154L;
private static final Date LAST_UPDATE_TS = new Date(DATE_LONG);
#Autowired
MessageDao MessageDao;
#BeforeMethod
public void setUp() throws Exception {
this.setDao(MessageDao);
}
#Test
#Transactional
public void testFindMessages() throws Exception {
List<Message> Messages = this.MessageDao.findMessages(ACCOUNT_ID, LAST_UPDATE_TS);
Assert.assertNotNull(Messages);
Assert.assertEquals(Messages.size(), 1);
}
}
Abstract test class, that extends from TestNG's class:
import com.github.springtestdbunit.DbUnitTestExecutionListener;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.test.context.support.DirtiesContextTestExecutionListener;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
import org.springframework.transaction.annotation.Transactional;
#TestExecutionListeners({ DependencyInjectionTestExecutionListener.class,
DirtiesContextTestExecutionListener.class,
TransactionalTestExecutionListener.class,
DbUnitTestExecutionListener.class })
#ContextConfiguration(locations = { "classpath:test-context.xml" })
public class AbstractDaoTest <T> extends AbstractTestNGSpringContextTests {
private GenericDao<T> dao;
#Transactional
public T create(T t){
return dao.create(t);
}
#Transactional
public void delete(Object id){
dao.delete(id);
}
#Transactional
public T find(Object id){
return dao.find(id);
}
#Transactional
public T update(T t){
return dao.update(t);
}
public void setDao(GenericDao<T> dao) {
this.dao = dao;
}
}
Finally, the Entity:
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import javax.persistence.*;
#NamedQueries({
#NamedQuery(
name = "findMessagesQuery",
query = "select om from Message om where om.recipientAccount.id=:accountId " +
"and om.lastUpdatedTs>:time and om.lastUpdatedTs+om.expirationPeriod>:now " +
"order by om.lastUpdatedTs asc"
),
#NamedQuery(
name = "findExpiredMessagesQuery",
query = "select om from Message om where om.lastUpdatedTs+om.expirationPeriod<:now"
)
})
#Entity
#Table(name="mp_message")
public class Message extends AbstractModel {
#JoinColumn(name="recipient_account_id", updatable = false)
#ManyToOne(optional = false, fetch = FetchType.LAZY)
private Account recipientAccount;
#JoinColumn(name="sender_account_id", updatable = false)
#ManyToOne(optional = false, fetch = FetchType.LAZY)
private Account senderAccount;
#Column(name="message_body", length=2048)
private String messageBody;
#Column(name="expiration_period")
private Long expirationPeriod;
// Getters, setters, etc excluded for brevity
}
Just a sidenote: I have "obscured" the Entity name (dammned lawyers!), so there could be some small name mistakes. Please bear with me on this ;)
If you need some additional details, please let me know.
Thanks in advance
try to add classpath: before your path, so:
#DatabaseSetup("classpath:data/message.xml")
Just do this, it works. the relative path can be used.
#DatabaseSetup("/data/message.xml"")

Resources