restTemplate returns "Count not extract response" exception - spring

I have following code to consume a REST webservice and convert the results;however, when I run the code it returns following exception, I am also not sure how to handle other type of responses for example if a response with error code in its body is returned. I have found this questions 1 and 2 with similar topics but did not find much there.
Exception
org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [class com.project.web.FlightsResults] and content type [application/xml]
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:110)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:576)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:537)
at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:244)
at com.project.web.ArticleController.showArticles(ArticleController.java:36)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
....
The rest template code is as following:
RestTemplate restTemplate = new RestTemplate();
Map<String, String> vars = new HashMap<String, String>();
vars.put("user", "username");
vars.put("key", "password");
vars.put("fl", "po");
AvailabilityResponse flightResults = restTemplate
.getForObject(
"http://example.com/availabilityRequest?user={user}&key={key}&fl_type={fl}",
AvailabilityResponse.class, vars);
System.err.println(">>"
+ flightResults.getFlightList().get(0).getFlightOptions()
.getFlightOption().size());
XMLElements
#XmlRootElement(name = "availabilityResponse")
#XmlAccessorType(XmlAccessType.FIELD)
public class AvailabilityResponse {
#XmlElement(name = "flightList")
private List<FlightList> flightList;
public AvailabilityResponse() {
this.flightList = new ArrayList();
}
public List<FlightList> getFlightList() {
return flightList;
}
public void setFlightList(List<FlightList> flightList) {
this.flightList = flightList;
}
}
#XmlRootElement(name = "flightList")
#XmlAccessorType(XmlAccessType.FIELD)
public class FlightList {
#XmlElement(name = "flightOptions")
private FlightOptions flightOptions;
public FlightOptions getFlightOptions() {
return flightOptions;
}
public void setFlightOptions(FlightOptions flightOptions) {
this.flightOptions = flightOptions;
}
}
#XmlRootElement(name = "flightOptions")
#XmlAccessorType(XmlAccessType.FIELD)
public class FlightOptions {
#XmlElement(name = "flightOption")
private List<FlightOption> flightOption;
public FlightOptions() {
this.flightOption = new ArrayList();
}
public List<FlightOption> getFlightOption() {
return flightOption;
}
public void setFlightOption(List<FlightOption> flightOption) {
this.flightOption = flightOption;
}
}
#XmlRootElement(name = "flightOption")
#XmlAccessorType(XmlAccessType.FIELD)
public class FlightOption {
#XmlElement(name = "viaIata")
private String viaIata;
#XmlElement(name = "fromDate")
private String fromDate;
#XmlElement(name = "toDate")
private String toDate;
#XmlElement(name = "fromTime")
private String fromTime;
#XmlElement(name = "toTime")
private String toTime;
#XmlElement(name = "flightNum")
private String flightNum;
#XmlElement(name = "class")
private String fclass;
#XmlElement(name = "flightlegs")
private List<FlightLeg> flightLegs;
#XmlElement(name = "prices")
private Prices prices;
public FlightOption() {
this.flightLegs = new ArrayList();
this.prices = new Prices();
}
getters and setters
#XmlRootElement (name = "prices")
#XmlAccessorType (XmlAccessType.FIELD)
public class Prices {
#XmlElement (name ="adult")
private float adult;
#XmlElement (name ="child")
private float child;
#XmlElement (name = "infant")
private float infant;
#XmlElement (name = "total")
private Total total;
getters and setters
#XmlRootElement (name = "total")
#XmlAccessorType (XmlAccessType.FIELD)
public class Total {
#XmlAttribute (name ="serviceCharge")
private float serviceCharge;
#XmlAttribute (name = "taxCharge")
private float taxCharge;
#XmlAttribute (name ="taxGeneral")
private float taxGeneral;
#XmlAttribute (name = "totalPrice")
private float totalPrice;
#XmlAttribute (name ="currency")
private String currency;
getters and setters
REST response
<availabilityResponse version="3">
<flightList fromIata="FRA" toIata="YYZ" flightsFound="8">
<flightOptions>
<flightOption>
<viaIata>FRA-YHZ-YYZ</viaIata>
<fromDate>2015-06-06</fromDate>
<fromTime>13:15:00</fromTime>
<toDate>2015-06-06</toDate>
<toTime>20:10:00</toTime>
<flightNum>DEA062</flightNum>
<class>C</class>
<flightlegs>
<flightlegdetail fromIata="FRA" toIata="YHZ">
<fromDate>2015-06-06</fromDate>
<fromTime>13:15:00</fromTime>
<toDate>2015-06-06</toDate>
<toTime>15:35:00</toTime>
<flightNum>DE6062</flightNum>
</flightlegdetail>
</flightlegs>
<flightlegs>
<flightlegdetail fromIata="YHZ" toIata="YYZ">
<fromDate>2015-06-06</fromDate>
<fromTime>18:50:00</fromTime>
<toDate>2015-06-06</toDate>
<toTime>20:10:00</toTime>
<flightNum>WS269</flightNum>
</flightlegdetail>
</flightlegs>
<prices currency="EUR" specialOffer="true">
<adult>724.22</adult>
<child>725.00</child>
<infant>73.00</infant>
<total serviceCharge="0.00" taxCharge="85.77" taxGeneral="85.77"
flightPrice="724.22" totalPrice="809.99" currency="EUR" />
</prices>
</flightOption>
<flightOption>
<viaIata>FRA-YYZ</viaIata>
.....

Your exception is because you have not registered message convertors for handling xml responses returned from the service. You can use xstream marshallers etc and there are plenty of example out there in web.
http://www.informit.com/guides/content.aspx?g=java&seqNum=546
https://spring.io/blog/2009/03/27/rest-in-spring-3-resttemplate

Related

Spring boot JPARepository doesn't execute save

Im building a simple app in spring boot and having problems with saving an entity to the db. The bank account is saved normally, but the transaction is not being saved.
The weird thing is that there are no errors or anything. On the first transactionRepository call the method is exited and the app continues normally. I don't get any message in the console or and didn't find any problems using debugging.
Here is the makeTransaction() method, which executes normally until transactionRepository.save(...)
public void makeTransaction(Iban sourceIban, Iban destinationIban, double amount)
throws Exception {
BankAccountEntity sourceAccount = getBankAccountByIban(sourceIban);
BankAccountEntity destinationAccount = getBankAccountByIban(destinationIban);
Date currentDate = new Date();
TransactionEntity sourceTransaction = new TransactionEntity(sourceAccount, sourceIban, destinationIban, currentDate, amount);
TransactionEntity destinationTransaction = new TransactionEntity(destinationAccount, sourceIban, destinationIban, currentDate, amount);
if (sourceAccount.getAmountDeductible() < amount || amount < 0) { // TODO amount checker
throw new Exception(ILLEGAL_TRANSACTION_AMOUNT_TEXT); // TODO change exception type
}
sourceAccount.reduceBalance(amount);
sourceAccount.addTransaction(sourceTransaction);
destinationAccount.increaseBalance(amount);
destinationAccount.addTransaction(destinationTransaction);
bankAccountRepository.save(sourceAccount);
bankAccountRepository.save(destinationAccount);
transactionRepository.save(sourceTransaction);
transactionRepository.saveAndFlush(destinationTransaction);
}
The class has the repositories initialized as follows
private final BankAccountRepository bankAccountRepository;
private final TransactionRepository transactionRepository;
public BankAccountService(#Autowired BankAccountRepository bankAccountRepository,
#Autowired TransactionRepository transactionRepository) {
this.bankAccountRepository = bankAccountRepository;
this.transactionRepository = transactionRepository;
}
The BankAccountRepository looks like this
public interface BankAccountRepository extends JpaRepository<BankAccountEntity, UUID> {
Optional<BankAccountEntity> findByIban(String iban);
}
And the TransactionRepository like this
public interface TransactionRepository extends JpaRepository<TransactionEntity, UUID> {}
The TransactionEntity looks like this
#Entity
#Table(name = "transactions")
public class TransactionEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "transaction_id", nullable = false)
#Type(type = "uuid-char")
private Long transactionId;
private String sourceIban;
private String destinationIban;
private long dateExecuted;
private double amount;
#ManyToOne
#JoinColumn(name = "bank_account_id")
private BankAccountEntity bankAccount;
public TransactionEntity() {
}
public TransactionEntity(BankAccountEntity bankAccount, Iban sourceIban, Iban destinationIban, Date dateExecuted, double amount) {
this.bankAccount = bankAccount;
this.sourceIban = sourceIban.toString();
this.destinationIban = destinationIban.toString();
this.amount = amount;
this.dateExecuted = dateExecuted.getTime();
}
public BankAccountEntity getBankAccount() {
return bankAccount;
}
public void setBankAccount(BankAccountEntity bankAccount) {
this.bankAccount = bankAccount;
}
public Long getTransactionId() {
return transactionId;
}
public void setTransactionId(Long transactionId) {
this.transactionId = transactionId;
}
}

ModelMapper issue with mapping basic POJOS

I have 2 basic POJOs that i use to build a json object :
public class ProductCreateRequestModel {
private String name;
private double price;
private int qty;
private String imgPath;
private CategoryRequestCreateProductModel category;
}
public class CategoryRequestCreateProductModel {
private String name;
private String categoryKeyId;
}
Basically it allow me to use a simple json like this one :
{
"name": "Pizza,
"price": 344.0,
"qty": 15,
"imgPath": "new/pathImage",
"category": {
"categoryKeyId": "23ume70Fu6yqyGUWfQkW110P4ko3gZ",
"name": "Starter"
}
}
I want to send this JSON and persist datas and i expect an object in return that i build with this POJO:
public class ProductRest {
private String productKeyId;
private String name;
private double price;
private int qty;
private String imgPath;
private CategoryRest category;
}
In my controller i just have to call a method which use PostMapping
#PostMapping(
consumes = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE },
produces = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE }
)
public ProductRest createProduct(#RequestBody ProductCreateRequestModel productCreateRequestModel) throws Exception {
ProductRest returnValue = new ProductRest();
if(productCreateRequestModel.getName().isEmpty() || productCreateRequestModel.getPrice() <= 0)
throw new ApplicationServiceException(ErrorMessages.MISSING_REQUIRED_FIELDS.getErrorMessage());
ModelMapper modelMapper = new ModelMapper();
ProductDto productDto = modelMapper.map(productCreateRequestModel, ProductDto.class);
ProductDto createdProduct = productService.createProduct(productDto);
returnValue = modelMapper.map(createdProduct, ProductRest.class);
return returnValue;
}
My service layer is actually doing nothing special :
#Override
public ProductDto createProduct(ProductDto productDto) {
return productDto;
}
My DTO layer contains the following fields :
#Getter #Setter
public class ProductDto implements Serializable {
// ommit this member and do not generate getter / setter
#Getter(AccessLevel.NONE)
#Setter(AccessLevel.NONE)
private static final long serialVersionUID = 1L;
private Long id;
private String productKeyId;
private String name;
private double price;
private int availableQty;
private String imgPath;
private CategoryDto category = new CategoryDto();
}
#Getter #Setter
public class CategoryDto implements Serializable {
#Getter(AccessLevel.NONE)
#Setter(AccessLevel.NONE)
private static final long serialVersionUID = 1L;
private long id;
private String categoryKeyId;
private String name;
private CategoryDto parentCategory;
private List<CategoryDto> subCategories;
private String parentCategoryKeyId;
private Long parentCategoryId;
}
While trying to run this basic code I obtain an error message :
java.lang.NumberFormatException: For input string: "23ume70Fu6yqyGUWfQkW110P4ko3gZ"

jpa with https request multithreading spring

I'm working with spring JPA and HTTP post request, fetching the data row by row then post the data into HTTP request to API and its worked fine with me, but here im working with bulk number of data, so i have to use multi-threading but im new with java and spring how do I implement to work with 10 thread and each one of them reads 1k per each time in parallel that here ?
i have read something about multithreading for 10 threads each thread of them read 1k row per each time, I have around 10 million records in my database
AccessingDataJpaApplication class :
#SpringBootApplication
public class AccessingDataJpaApplication implements CommandLineRunner {
private static final Logger logger = LoggerFactory.getLogger(AccessingDataJpaApplication.class);
#Autowired
private Bulk_repositoryRepository bulk_repositoryRepository;
public static void main(String[] args) {
SpringApplication.run(AccessingDataJpaApplication.class);
}
Date currentDate = new Date();
#Override
public void run(String... args) throws Exception {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
headers.setBasicAuth("user", "pass");
while(true) {
Date currentDate = new Date();
logger.info("Just Started");
for (Bulk_repository churnss : bulk_repositoryRepository.findAllByStatusAndCampTypeAndCampStartDateLessThanEqualAndCampEndDateGreaterThanEqual(0,2,currentDate,currentDate)) {
System.out.print(churnss);
logger.info(churnss.toString());
AddOfferRequest AddOffer = new AddOfferRequest("113", churnss.getMsisdn(),churnss.getParam1());
logger.info(AddOffer.toString());
HttpEntity<AddOfferRequest> entity = new HttpEntity<AddOfferRequest>(AddOffer,headers);
ResponseEntity<String> responseEntity = restTemplate.exchange(
"api link", HttpMethod.POST, entity, String.class);
if(responseEntity.getStatusCode() == HttpStatus.OK){
String response = responseEntity.getBody();
churnss.setStatus(1);
churnss.setProcessDate(new Date());
churnss.setFulfilment_status(response);
logger.info(churnss.toString() + ", Response: " + response);
bulk_repositoryRepository.save(churnss);
}else {
logger.warn("Record Id: " + churnss.getId() + ", Http Failed Response: " + responseEntity.getStatusCode());
}
}
Thread.sleep(1000);
}
}
}
Bulk_repository class:
#Entity
#Table(name = "BULK_REPOSITORY")
public class Bulk_repository {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name = "id")
private long id;
#Column(name = "msisdn")
private String msisdn;
#Column(name = "camp_start_date")
private Date campStartDate;
#Column(name = "camp_end_date")
private Date campEndDate;
#Column(name = "camp_type")
private int campType;
#Column(name = "camp_cd")
private String camp_cd;
#Column(name = "status")
private int status;
#Column(name = "process_date")
private Date processDate;
#Column(name = "entry_date")
private Date entryDate;
#Column(name = "entry_user")
private String entry_user;
#Column(name = "param1")
private String param1;
#Column(name = "param2")
private String param2;
#Column(name = "param3")
private String param3;
#Column(name = "param4")
private String param4;
#Column(name = "param5")
private String param5;
#Column(name = "error_desc")
private String error_desc;
#Column(name = "fulfilment_status")
private int fulfilment_status;
##then getter and setters and tostring
Bulk_repositoryRepository class :
public interface Bulk_repositoryRepository extends CrudRepository<Bulk_repository, Long> {
Date today = new Date();
List<Bulk_repository>findAllByStatusAndCampTypeAndCampStartDateLessThanEqualAndCampEndDateGreaterThanEqual(int status, int campType,Date today0, Date today1);
Bulk_repository findById(long id);
}
AddOfferRequest class :
public class AddOfferRequest {
private String ChannelID="113";
private String MSISDN;
private String ServiceID;
public AddOfferRequest() {
}
public AddOfferRequest(String channelID,String mSISDN,String serviceID ) {
this.MSISDN = mSISDN;
this.ServiceID = serviceID;
}
## then getter and setter and tostring
i have created AsyncConfiguration class:
package com.example.accessingdatajpa;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
#Configuration
#EnableAsync
public class AsyncConfiguration {
private static final Logger LOGGER = LoggerFactory.getLogger(AsyncConfiguration.class);
#Bean (name = "taskExecutor")
public Executor taskExecutor() {
LOGGER.debug("Creating Async Task Executor");
final ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(2);
executor.setQueueCapacity(1000);
executor.setThreadNamePrefix("CarThread-");
executor.initialize();
return executor;
}
}
but till now i can't undertand how can combaine the findby and http post with multithreading
Rewrite your code. Instead of a List<Bulk_repository> return a Stream<Bulk_repository>. This will lazily load the records from the database, instead of trying to do everything at once.
Then use the TaskExecutor to execute the different requests per thread, just give a task to it and it will be executed when there is a free thread.
#SpringBootApplication
public class AccessingDataJpaApplication implements CommandLineRunner {
private static final Logger logger = LoggerFactory.getLogger(AccessingDataJpaApplication.class);
#Autowired
private Bulk_repositoryRepository bulk_repositoryRepository;
#Autowired
private AsyncTaskExecutor executor;
#Autowired
private RestTemplate rest;
public static void main(String[] args) {
SpringApplication.run(AccessingDataJpaApplication.class);
}
#Override
public void run(String... args) throws Exception {
Date currentDate = new Date();
Stream< Bulk_repository> results = Bulk_repository churnss : bulk_repositoryRepository.findAllByStatusAndCampTypeAndCampStartDateLessThanEqualAndCampEndDateGreaterThanEqual(0,2,currentDate,currentDate);
results.forEach(it -> executor.submit(this.process(it)));
Thread.sleep(1000);
}
private void process(RestTemplate rest, Bulk_repository churnss) {
AddOfferRequest AddOffer = new AddOfferRequest("113", churnss.getMsisdn(),churnss.getParam1());
HttpEntity<AddOfferRequest> entity = new HttpEntity<AddOfferRequest>(AddOffer,headers);
try {
ResponseEntity<String> responseEntity = restTemplate.exchange(
"api link", HttpMethod.POST, entity, String.class);
if(responseEntity.getStatusCode() == HttpStatus.OK){
String response = responseEntity.getBody();
churnss.setStatus(1);
churnss.setProcessDate(new Date());
churnss.setFulfilment_status(response);
bulk_repositoryRepository.save(churnss);
}else {
logger.warn("Record Id: {}, Http Failed Response: {}",churnss.getId(), responseEntity.getStatusCode());
}
} catch (RestClientException rce) {
logger.warn("Record Id: {} Http Failed. ", churnss.getId(), rce);
}
}
}
NOTE: This was typed from the top of my head and isn't tested. However should provide some guidance.
Using #Async annotations to implement mutithread in spring. It can help you.
https://spring.io/guides/gs/async-method/
https://docs.spring.io/spring-data/rest/docs/2.0.0.M1/reference/html/paging-chapter.html
Try with Batch Insert/Update with Hibernate/JPA. Here is a nice tutorial
spring.jpa.properties.hibernate.jdbc.batch_size=500

marshall attributes inside XML elements with JAXB

I work with Spring JPA and have the following entity:
#Entity
#Table(name = Constants.ENTITY_TABLE_PREFIX + "ENTRY")
#XmlAccessorType(XmlAccessType.NONE)
#XmlRootElement(name = "monObj_info")
public class EntryXML implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "ID")
#GeneratedValue(strategy = GenerationType.IDENTITY)
#XmlAttribute
private long id;
#Column(name = "ip_address", nullable = true)
#XmlElement
private String ip_address;
#Column(name = "network_element_name", nullable = false)
#XmlElement
private String network_element_name;
public EntryXML() {}
public EntryXML(long id, String ip_address, String network_element_name) {
super();
this.id = id;
this.ip_address = ip_address;
this.network_element_name = network_element_name;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getIp_address() {
return ip_address;
}
public void setIp_address(String ip_address) {
this.ip_address = ip_address;
}
public String getNetwork_element_name() {
return network_element_name;
}
public void setNetwork_element_name(String network_element_name) {
this.network_element_name = network_element_name;
}
}
and the endpoint:
#RestController
public class EntryXMLEndpoint {
#Autowired
private IEntryXMLService service;
#RequestMapping(value = "/restxml", produces = { "application/xml" })
public EntryXML findEntries() {
EntryXML record = service.findById(1);
return record;
}
}
Now the requested response is:
<monObj_info id="1">
<atribute name="ip_address" value="xx.xxx.xxx.x"/>
<atribute name="network_element_name" value="xxxxxx"/>
</monObj_info>
Of course what I get is :
<monObj_info id="1">
<ip_address>xx.xxx.xxx.x</ip_address>
<network_element_name>xxxxxx</network_element_name>
</monObj_info>
I read similar posts , but the problem is I cannot create a List with the required elements inside my Entity Class, since it will not map with any column in the respective table, any suggestions?
You can achieve your goal in a straight-forward but somewhat hackish way.
Since you don't want the ip_address and network_element_name properties
to be marshalled and unmarshalled directly, you need to remove their #XmlElement annotation
and add #XmlTransient.
Instead, you want some <atribute name="..." value="..." /> elements marshalled and unmarshalled.
Therefore you need to add the following things to your EntryXML class:
an attributes property holding a list of attributes.
It is annotated with #XmlElement so that it will be part of XML marshalling and unmarshalling.
It is annotated with #Transient so that it will not be part of database persistence.
a simple helper class Attribute for holding name and value.
name and value are annotated with #XmlAttribute so that they will be part of XML marshalling and unmarshalling.
a Marshal Event Callback (beforeMarshal)
for doing the conversion from ip_address and network_element_name
to the attributes list.
an Unmarshal Event Callback (afterUnmarshal)
for doing the opposite conversion.
#XmlElement(name = "atribute")
#Transient // from package javax.persistence
private List<Attribute> attributes;
// there is no need for getAttributes and setAttributes methods
private static class Attribute {
#SuppressWarnings("unused") // called by the unmarshaller
Attribute() {
}
Attribute(String name, String value) {
this.name = name;
this.value = value;
}
#XmlAttribute
private String name;
#XmlAttribute
private String value;
}
#SuppressWarnings("unused") // this method is called only by the marshaller
private boolean beforeMarshal(Marshaller marshaller) {
attributes = new ArrayList<>();
attributes.add(new Attribute("ip_address", ip_address));
attributes.add(new Attribute("network_element_name", network_element_name));
return true;
}
#SuppressWarnings("unused") // this method is called only by the unmarshaller
private void afterUnmarshal(Unmarshaller unmarshaller, Object parent) {
if (attributes != null) {
for (Attribute attribute : attributes) {
switch (attribute.name) {
case "ip_address":
ip_address = attribute.value;
break;
case "network_element_name":
network_element_name = attribute.value;
break;
}
}
}
}
Then the XML output will look like this:
<monObj_info id="1">
<atribute name="ip_address" value="xx.xxx.xxx.x"/>
<atribute name="network_element_name" value="xxxxxx"/>
</monObj_info>

Dynamic type caste Spring pathvariable

I am planning to create one simple Spring Rest Service Project with JPA which will fetch the details from the database based on the entity name and entity id given in path variables.
consider following code.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
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.ResponseBody;
import com.ds.dao.EntityDAO;
import com.ds.entities.Employees;
import javax.persistence.Entity;
#Controller
#RequestMapping("/")
public class DynaRestController {
#Autowired
EntityDAO entityDAO;
#RequestMapping(value = "{entityName}/{enityId}",method = RequestMethod.GET)
public #ResponseBody Object getEntity(#PathVariable("entityName") String entityName,#PathVariable("enityId") Object id) {
return entityDAO.getEntityById(entityName, id);
}
}
Entity DAO Class
public class EntityDAO {
#Autowired
EntityManager entityManager;
public Object getEntityById(String entityName, Object id) {
EntityType<?> entityType = getEntityByName(entityName);
Object idcasted = entityType.getIdType().getJavaType().cast(id);
System.out.println(idcasted.getClass().getName());
Object entity = entityManager.find(entityType.getJavaType(), idcasted);
System.out.println("Entity.. Name .." + entityName);
// Employees entity = session.load(Employees.class, id);
return entity;
}
private EntityType<?> getEntityByName(String name) {
Set<EntityType<?>> entities = entityManager.getMetamodel().getEntities();
for (Iterator<EntityType<?>> iterator = entities.iterator(); iterator.hasNext();) {
EntityType<?> entityType = (EntityType<?>) iterator.next();
if (entityType.getName().equals(name))
return entityType;
}
return null;
}
}
Employees Class
#Configurable
#Entity
#Table(name = "employees", catalog = "employees")
public class Employees implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private int empNo;
private Date birthDate;
private String firstName;
private String lastName;
private String gender;
private Date hireDate;
private Set<Titles> titleses = new HashSet<Titles>(0);
private Set<Salaries> salarieses = new HashSet<Salaries>(0);
private Set<DeptEmp> deptEmps = new HashSet<DeptEmp>(0);
private Set<DeptManager> deptManagers = new HashSet<DeptManager>(0);
public Employees() {
}
public Employees(int empNo, Date birthDate, String firstName, String lastName, String gender, Date hireDate) {
this.empNo = empNo;
this.birthDate = birthDate;
this.firstName = firstName;
this.lastName = lastName;
this.gender = gender;
this.hireDate = hireDate;
}
public Employees(int empNo, Date birthDate, String firstName, String lastName, String gender, Date hireDate,
Set<Titles> titleses, Set<Salaries> salarieses, Set<DeptEmp> deptEmps, Set<DeptManager> deptManagers) {
this.empNo = empNo;
this.birthDate = birthDate;
this.firstName = firstName;
this.lastName = lastName;
this.gender = gender;
this.hireDate = hireDate;
this.titleses = titleses;
this.salarieses = salarieses;
this.deptEmps = deptEmps;
this.deptManagers = deptManagers;
}
#Id
#Column(name = "emp_no", unique = true, nullable = false)
public int getEmpNo() {
return this.empNo;
}
public void setEmpNo(int empNo) {
this.empNo = empNo;
}
#Temporal(TemporalType.DATE)
#Column(name = "birth_date", nullable = false, length = 10)
public Date getBirthDate() {
return this.birthDate;
}
public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
#Column(name = "first_name", nullable = false, length = 14)
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
#Column(name = "last_name", nullable = false, length = 16)
public String getLastName() {
return this.lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
#Column(name = "gender", nullable = false, length = 2)
public String getGender() {
return this.gender;
}
public void setGender(String gender) {
this.gender = gender;
}
#Temporal(TemporalType.DATE)
#Column(name = "hire_date", nullable = false, length = 10)
public Date getHireDate() {
return this.hireDate;
}
public void setHireDate(Date hireDate) {
this.hireDate = hireDate;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "employees")
public Set<Titles> getTitleses() {
return this.titleses;
}
public void setTitleses(Set<Titles> titleses) {
this.titleses = titleses;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "employees")
public Set<Salaries> getSalarieses() {
return this.salarieses;
}
public void setSalarieses(Set<Salaries> salarieses) {
this.salarieses = salarieses;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "employees")
#JsonBackReference
public Set<DeptEmp> getDeptEmps() {
return this.deptEmps;
}
public void setDeptEmps(Set<DeptEmp> deptEmps) {
this.deptEmps = deptEmps;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "employees")
public Set<DeptManager> getDeptManagers() {
return this.deptManagers;
}
public void setDeptManagers(Set<DeptManager> deptManagers) {
this.deptManagers = deptManagers;
}
}
When i am dynamically casting the path variable by using following code
Object idcasted = entityType.getIdType().getJavaType().cast(id);
Object entity = entityManager.find(entityType.getJavaType(), idcasted);
it is throwing ClassCastExpcetion
java.lang.ClassCastException: Cannot cast java.lang.String to int
at java.lang.Class.cast(Class.java:3369) ~[na:1.8.0_112]
at com.techm.att.ds.dao.EntityDAO.getEntityById(EntityDAO.java:33) ~[classes/:na]
at com.techm.att.ds.dao.EntityDAO$$FastClassBySpringCGLIB$$8e64d745.invoke() ~[classes/:na]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:738) ~[spring-aop-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136) ~[spring-tx-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.13.RELEASE.jar:4.3.13.RELEASE]
any Help will be highly appriciated..
I write you a simple example regarding the comments.
This is the same behavior. Your RestController gets actually a string:
public static void main(String[] args) {
Object myString = "myString";
System.out.println(myString.getClass()); // class java.lang.String
int.class.cast(myString);
}
The cast method checks the instanceof your given value and it fails:
public T cast(Object obj) {
if (obj != null && !isInstance(obj))
throw new ClassCastException(cannotCastMsg(obj));
return (T) obj;
}

Resources