How to wrap the query in a view in the database - java

I need to extract a view that is coming out of a #Query in my repository to a table in another database, I'm in a Multi-Tenacy connection, in it I have a view that I can visualize, and this view wanted to transport it directly to a table of another bank that is connected with the API,
it would look a bit like this example:
site
#Repository
public interface example extends JpaRepository<example,Long>{
#Query(nativeQuery = true, value = "CREATE OR REPLACE VIEW FINANCEIRO AS SELECT " +
" example," +
" example," +
" example," +
" example," +
" example," +
" example," +
" example," +
" example," +
" example," +
" example," +
" example," +
" example," +
" example," +
" example" )
List<Object> projection();`
this view above it returns everything as expected, now I wanted it to go straight to a table in another bank in my Multi-Tenacy connection
My #GetMapping
#GetMapping
public List<Object> projecao(){
return repository.projection2();
}

I tried to do this but I get a DDL error
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.Immutable;
import org.springframework.data.jpa.repository.Query;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.math.BigDecimal;
#Entity
#NoArgsConstructor
#AllArgsConstructor
#Data
#Table(name = "example_example SELECT " +
" example," +
" example," +
" example," +
" example," +
" example," +
" example," +
" example," +
" example," +
" example," +
" example," +
" example," +
" example," +
" example," +
" example FROM example" )
public class example {
#Id
private Long id;
#Column(name = "example")
private String example;
#Column(name = "example")
private String example;
#Column(name = "example")
private String example;
#Column(name = "example")
private String example;
#Column(name = "example")
private BigDecimal example;
#Column(name = "example")
private BigDecimal example;
#Column(name = "example")
private BigDecimal example;
#Column(name = "example")
private Integer example;
#Column(name = "example")
private String example;
#Column(name = "example")
private Integer example;
#Column(name = "example")
private String example;
#Column(name = "example")
private String example;
#Column(name = "example")
private String example;
#Column(name = "example")
private Integer example;
}

Related

o.h.engine.jdbc.spi.SqlExceptionHelper: ERROR: Column cliententi0_.name does not exist

Repostory
#Repository
public interface ClientRepository extends JpaRepository<ClientEntity, Long> {
#Modifying
#Transactional
#Query(value = "SELECT pp.id, TO_CHAR(pp.created_dt::date, 'dd.mm.yyyy')\n" +
"AS 'Data', CAST(pp.created_dt AS time(0)) AS 'Time', au.username AS 'UserName',\n" +
"ss.name AS 'Service', pp.amount AS 'Amount',\n" +
"REPLACE(pp.status, 'SUCCESS', 'Success') AS 'Payment_status', pp.account AS 'Account',\n" +
"pp.external_id AS 'Idn', COALESCE(pp.external_status, null, 'DN')\n" +
"AS 'Stat'\n" +
"FROM payments AS pp\n" +
"INNER JOIN user AS au ON au.id = pp.creator_id\n" +
"INNER JOIN services AS ss ON ss.id = pp.service_id\n" +
"WHERE pp.created_dt >= '2021-09-28'\n" +
"AND ss.name = 'Faberlic' AND pp.status = 'SUCCESS'", nativeQuery = true)
List<Client> getAllByRegDate();
}
Inteface
public interface Client {
Long getId();
#JsonFormat(shape = JsonFormat.Shape.STRING)
LocalDate getCreated_dt();
String getUsername();
String getName();
int getAmount();
String getStatus();
String getAccount();
String getExternal_id();
String getExternal_status();
}
DTO
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#ToString
public class ClientDto {
private Long id;
#JsonFormat(shape = JsonFormat.Shape.STRING)
private LocalDate created_dt;
private String username;
private String name;
private int amount;
private String status;
private String account;
private String external_id;
private String external_status;
public ClientDto(Client client) {
this.id = client.getId();
/...
/...
this.external_status = client.getExternal_status();
}
public ClientDto(ClientDto clientDto) {
this.id = clientDto.getId();
/...
this.external_status = clientDto.getExternal_status();
}
public ClientDto(ClientEntity clientEntity) {
}
#Override
public String toString() {
return "" + id + "|" + created_dt + "|" + username + "|" + name +
"|" + amount + "|" + status + "|" + account + "|" + external_id + "|" + external_status;
}
}
Entity
#Getter
#NoArgsConstructor
#AllArgsConstructor
#Immutable
#Entity
#Table(name = "payments", schema = "public")
public class ClientEntity {
#Id
private Long id;
#Column(name = "created_dt")
private LocalDate created_dt;
#Column(name = "username")
private String username;
#Column(name = "name")
private String name;
#Column(name = "amount")
private int amount;
#Column(name = "status")
private String status;
#Column(name = "account")
private String account;
#Column(name = "external_id")
private String external_id;
#Column(name = "external_status")
private String external_status;
}
I am trying to save data to a csv file. I take data from one database, from three tables. In entity #Table in "name" I specify one of the existing tables - "payment". All data is taken from three tables (as I have written in Query). But when program is run, an error appears that the "name" column does not exist. This column is in another table from which I am fetching data. Can't figure out what I should do.
This is more of an answer to this question and the question you asked here, combined. Imho you are making things overly complex with your structure of having a Client interface which is used as a projection, which is then turned into a ClientDto (why? the projection is already a DTO) and you have your entities.
Instead of doing this just use a JdbcTemplate with a RowCallbackHandler to write the rows to CSV. This will use a lot less memory, be faster (as you aren't creating multiple objects per row to then throw it away, and you don't have all the rows in memory).
import java.io.FileWriter;
import java.sql.ResultSet;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
#Component
public class SchedulerService {
private static final String QUERY = "SELECT pp.id, pp.created_dt au.username, ss.name, pp.amount\n" +
"REPLACE(pp.status, 'SUCCESS', 'Success'), pp.account,\n" +
"pp.external_id AS 'Idn', COALESCE(pp.external_status, null, 'DN') AS 'Stat'\n" +
"FROM payments AS pp\n" +
"INNER JOIN user AS au ON au.id = pp.creator_id\n" +
"INNER JOIN services AS ss ON ss.id = pp.service_id\n" +
"WHERE pp.created_dt >= '2021-09-28'\n" +
"AND ss.name = 'Faberlic' AND pp.status = 'SUCCESS'";
private static final DateTimeFormatter date_format = DateTimeFormatter.ofPattern("dd.MM.yyyy");
private static final DateTimeFormatter time_format = DateTimeFormatter.ofPattern("HH:mm:ss");
private final JdbcTemplate jdbc;
public SchedulerService(JdbcTemplate jdbc) {
this.jdbc = jdbc;
}
#Scheduled(fixedRate = 5000)
public void downloadBlockedClients() {
String filename = "select.csv";
try (FileWriter writer = new FileWriter(filename)) {
writer.append("id|date|time|username|name|amount|status|account|external_id|external_status").append('\n');
this.jdbc.query(QUERY, (ResultSet rs) -> writeLine(writer, rs));
} catch (Exception e) {
e.printStackTrace();
}
}
private void writeLine(FileWriter writer, ResultSet rs) {
try {
LocalDateTime ldt = rs.getTimestamp("created_dt").toLocalDateTime();
writer.append(String.valueOf(rs.getLong("id")));
writer.append('|');
writer.append(ldt.format(date_format));
writer.append('|');
writer.append(ldt.format(time_format));
writer.append('|');
writer.append(rs.getString("username"));
writer.append('|');
writer.append(rs.getString("name"));
writer.append('|');
writer.append(String.valueOf(rs.getBigDecimal("amount")));
writer.append('|');
writer.append(rs.getString("status"));
writer.append('|');
writer.append(rs.getString("account"));
writer.append('|');
writer.append(rs.getString("idn"));
writer.append('|');
writer.append(rs.getString("stat"));
writer.append('\n');
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
}
Something along these lines will make your resources more efficient (saves the copying, having results duplicated in memory) and should be faster. You could move the row handling to a method so your lambda gets a bit more readable.
NOTE: I assumed that you are using Spring Boot and that the `JdbcTemplate is available out-of-the-box. If not you need to configure one next to your JPA configuration.
#Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}

using toString on a "child" class where the "parent" is a Hiberneate/JPA class

I am working with REST APIs , Java, Hibernate and JPA.
I have a class Mstrgetnroletype (i.e. role type) that is part of another class called ApplicationUser.
class ApplicationUser
#Entity
#Table(name = "APPLICATIONUSER", schema = "orcl", uniqueConstraints = { #UniqueConstraint(columnNames = "EMAIL"),
#UniqueConstraint(columnNames = "USERNAME") })
public class ApplicationUser implements java.io.Serializable {
private BigDecimal id;
private Mstrgenroletype mstrgenroletype;
private Mstrgenyesno mstrgenyesnoByIsactive;
private Mstrgenyesno mstrgenyesnoByIsstaff;
private Mstrgenyesno mstrgenyesnoByIssuperuser;
[.. snip ..]
class Mstrgenroletype
#Entity
#Table(name = "MSTRGENROLETYPE", schema = "orcl")
public class Mstrgenroletype implements java.io.Serializable {
private BigDecimal mstrgenroletypeid;
private String langid;
private String shortdesc;
private String longdesc;
private Set<Applicationuser> applicationusers = new HashSet<Applicationuser>(0);
public Mstrgenroletype() {
}
public Mstrgenroletype(BigDecimal mstrgenroletypeid) {
this.mstrgenroletypeid = mstrgenroletypeid;
}
public Mstrgenroletype(BigDecimal mstrgenroletypeid, String langid, String shortdesc, String longdesc,
Set<Applicationuser> applicationusers) {
this.mstrgenroletypeid = mstrgenroletypeid;
this.langid = langid;
this.shortdesc = shortdesc;
this.longdesc = longdesc;
this.applicationusers = applicationusers;
}
#Id
#Column(name = "MSTRGENROLETYPEID", unique = true, nullable = false, precision = 22, scale = 0)
public BigDecimal getMstrgenroletypeid() {
return this.mstrgenroletypeid;
}
public void setMstrgenroletypeid(BigDecimal mstrgenroletypeid) {
this.mstrgenroletypeid = mstrgenroletypeid;
}
#Column(name = "LANGID", length = 2)
public String getLangid() {
return this.langid;
}
public void setLangid(String langid) {
this.langid = langid;
}
#Column(name = "SHORTDESC", length = 10)
public String getShortdesc() {
return this.shortdesc;
}
public void setShortdesc(String shortdesc) {
this.shortdesc = shortdesc;
}
#Column(name = "LONGDESC", length = 20)
public String getLongdesc() {
return this.longdesc;
}
public void setLongdesc(String longdesc) {
this.longdesc = longdesc;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "mstrgenroletype")
public Set<Applicationuser> getApplicationusers() {
return this.applicationusers;
}
public void setApplicationusers(Set<Applicationuser> applicationusers) {
this.applicationusers = applicationusers;
}
#Override
public String toString() {
return "Mstrgenroletype [mstrgenroletypeid=" + mstrgenroletypeid + ", langid=" + langid + ", shortdesc="
+ shortdesc + ", longdesc=" + longdesc + "]";
}
}
I am trying to make a method of "toString" that will print out the contents of the variable associated with ApplicationUser.
The problem is that when printing out the contents of the variable associated with Mstrgenroletype, I get an error of
org.hibernate.LazyInitializationException: could not initialize proxy
- no Session
This is because it is trying to print the contents associated with the class of Mstrgenroletype. (I know this because when I remove the print statement assocaited with variable that is linked to the class, everything works)
BEFORE (getting the error)
#Override
public String toString() {
return "ApplicationUser [id=" + id + ", password=" + password + ", username=" + ", role=" + mstrgenroletype.toString()
+ username + ", firstname=" + firstname + ", lastname=" + lastname + ", email=" + email + ", userid="
+ userid + ", apptenantid=" + apptenantid + ", appkeyid=" + appkeyid + ", profilepic=" + profilepic + "]";
}
AFTER (Mstrgenroltype variable removed, getting no error)
#Override
public String toString() {
return "ApplicationUser [id=" + id + ", password=" + password + ", username="
+ userid + ", apptenantid=" + apptenantid + ", appkeyid=" + appkeyid + ", profilepic=" + profilepic + "]";
}
I have made sure that the class with Mstrgenroletype does have a toString method as well.
How can I print the variable associated with Mstrgenroletype?
You invoke the toString() method on a ApplicationUser object that didn't load the mstrgenroletype relationship eagerly.
As ApplicationUser.toString() method invokes the toString() method of the object referenced by mstrgenroletype, it throws an exception because the ApplicationUser object is currently a Hibernate proxy that can load relationship only in the frame of a Hibernate session.
But according to the thrown exception, you don't have any currently opened session during the toString() invocation.
How can I print the variable associated with Mstrgenroletype?
First, you should avoid having a toString() which the results depends on a persistence session.
It mix things. toString() is for debugging an object, not for fetching fields with query executions.
It is an important side effect you have to avoid.
So I advise to write a toString() method that relies only on own fields of the entity as this one you wrote in your workaround.
This rule should also be followed for equals() or hashCode() methods
Of course if functionally you need to retrieve the relationship, add it in your query with a fetch join.
If it is not the case and you want only to debug the object relationships you can add a breakpoint in your IDE in a class where the Hibernate session is opened and the object retrieved and dig into the relationship with IDE tools (display or execute feature in Eclipse).

Hibernate duplicated rows during select

Few month ago I've started my adventure with Hibernate 5. I'm creating a Spring Boot application which need to take data from database view.
I have created an JPA entity and write code responsible for running query and map results to ORM entity. The problem is that Hibernate generate proper query in traces, but returns duplicate of the first row as a list. Query created by Hibernate looks like:
select
revenuesum0_.revenueId as revenueI1_9_,
revenuesum0_.amount as amount2_9_,
revenuesum0_.calculatedDate as calculat3_9_,
revenuesum0_.revenueCalculatedDateId as revenueC4_9_,
revenuesum0_.categoryName as category5_9_,
revenuesum0_.timeSpan as timeSpan6_9_,
revenuesum0_.title as title7_9_,
revenuesum0_.userId as userId8_9_
from
RevenueSummaryView revenuesum0_
where
revenuesum0_.userId=?;
When I run it on DBeaver and in MySQL console it works, the result set is proper. Problem appear when I'm trying to take data using Java JPA Query execution. Code responsible for bug is here:
package org.pbt.dao;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.pbt.HibernateUtil;
import org.pbt.model.entity.ExpenseSummaryView;
import org.pbt.model.filter.Filter;
import org.springframework.stereotype.Repository;
import javax.persistence.Query;
import java.util.List;
#Repository
public class ExpenseSummaryViewDAOImpl implements ExpenseSummaryViewDAO {
private SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
#Override
public List<ExpenseSummaryView> getFiltered(Filter filter) {
Session session = this.sessionFactory.openSession();
String hql = "FROM ExpenseSummaryView WHERE userId = :userId ";
if (filter.getStartDate() != null && filter.getEndDate() != null) {
hql += "AND calculatedDate BETWEEN :startDate AND :endDate ";
} else if (filter.getStartDate() != null) {
hql += "AND calculatedDate >= :startDate ";
} else if (filter.getEndDate() != null) {
hql += "AND calculatedDate <= :endDate ";
}
Query query = session.createQuery(hql);
query.setParameter("userId", filter.getUserId());
if (filter.getStartDate() != null && filter.getEndDate() != null) {
query.setParameter("startDate", filter.getStartDate());
query.setParameter("endDate", filter.getEndDate());
} else if (filter.getStartDate() != null) {
query.setParameter("startDate", filter.getStartDate());
} else if (filter.getEndDate() != null) {
query.setParameter("endDate", filter.getEndDate());
}
List<ExpenseSummaryView> expenseSummaryViews = (List<ExpenseSummaryView>) query.getResultList();
session.close();
return expenseSummaryViews;
}
}
In a debug whole expenseSummaryViews list elements have the same object reference. The JPA entity looks like:
package org.pbt.model.entity;
import org.springframework.format.annotation.DateTimeFormat;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.time.LocalDate;
#Entity
#Table(name = "ExpenseSummaryView")
public class ExpenseSummaryView {
#Id
#Column(name = "expenseId")
private int id;
#Column(name = "expenseCalculatedDateId", nullable = false)
private int calculatedDateId;
#Column(name = "userId", nullable = false)
private int userId;
#Column(name = "title", nullable = false)
private String title;
#Column(name = "amount", nullable = false)
private double amount;
#DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
#Column(name = "calculatedDate", nullable = false)
private LocalDate calculatedDate;
#Column(name = "categoryName", nullable = false)
private String categoryName;
#Column(name = "timeSpan", nullable = false)
private String timeSpan;
public int getId() {
return id;
}
public int getCalculatedDateId() {
return calculatedDateId;
}
public int getUserId() {
return userId;
}
public String getTitle() {
return title;
}
public double getAmount() {
return amount;
}
public LocalDate getCalculatedDate() {
return calculatedDate;
}
public String getCategoryName() {
return categoryName;
}
public String getTimeSpan() {
return timeSpan;
}
#Override
public String toString() {
return "{id:" + id + ", calculatedDateId:" + calculatedDateId + ", userId:" + userId + ", title:" + title + ", amount:" + amount + ", calculatedDate:" + calculatedDate.toString() + ", categoryName:" + categoryName + "}";
}
}
It is worth to mention that in very similar case I used hibernate for taking rows from another view on the same db in the same application and it works normally, but in above case it doesn't.
Is there anyone who can help?
problem was caused because there were no real ID available on database, the expenseId field was not real ID in DB, after change it, source code start works normally.

ObjectMapper - JSON string to Java Object not working

I have a requirement where I need to convert JSON response from an API and send it as XML to the end client.
I am able to successfully receive JSON (output pasted below) from the API but unable to convert it to Java Objects using ObjectMapper. I don't get any errors; but when I return "GetCardInfo" object it is null.
I have tried searching through google but unable to find why it is not working. It will be a big help if someone can help me understand what is the issue with my code.
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import java.lang.Object;
import javax.annotation.Resource;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.ws.Response;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.json.JSONObject;
import org.json.XML;
import org.slf4j.ext.XLogger;
import org.slf4j.ext.XLoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import com.bhn.webservice.ivr.CardActivationResponse;
import com.bhn.webservice.ivr.CardInfo;
import com.bhn.webservice.ivr.ErrorDetails;
import com.bhn.webservice.ivr.GetCardInfo;
import com.bhn.webservice.ivr.GetCardInfoReceiveJSONResponse;
import com.bhn.webservice.ivr.GetCardInfoRequest;
import com.bhn.webservice.ivr.GetCardInfoResponse;
import com.bhn.webservice.ivr.GetCardInfoSendJSONRequest;
import com.bhn.webservice.ivr.GetCardTransactionsReceiveJSONResponse;
import com.bhn.webservice.ivr.GetCardTransactionsRequest;
import com.bhn.webservice.ivr.GetCardTransactionsResponse;
import com.bhn.webservice.ivr.GetCardTransactionsSendJSONRequest;
import com.bhn.webservice.ivr.IVRKPNResponse;
import com.bhn.webservice.ivr.IVRResponse;
import com.bhn.webservice.ivr.IVRWrapperConstants;
import com.bhn.webservice.ivr.IVRWrapperResponse;
import com.bhn.webservice.ivr.RequestContext;
import com.bhn.webservice.ivr.VerifyCardConvertResponse;
import com.bhn.webservice.ivr.VerifyCardHolderReceiveJSONResponse;
import com.bhn.webservice.ivr.VerifyCardHolderRequest;
import com.bhn.webservice.ivr.VerifyCardHolderResponse;
import com.bhn.webservice.ivr.VerifyCardHolderSendJSONRequest;
import com.bhn.webservice.ivr.VerifyCardReceiveJSONResponse;
import com.bhn.webservice.ivr.VerifyCardRequest;
import com.bhn.webservice.ivr.VerifyCardResponse;
import com.bhn.webservice.ivr.VerifyCardSendJSONRequest;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
//XML mapper.
ObjectMapper mapper = new XmlMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
false);
mapper.enable(SerializationFeature.INDENT_OUTPUT);
GetCardInfo gci = mapper.readValue(JSONResponse.toString(),GetCardInfo.class);
Below is the output from JSONResponse.toString()
{
"transactionId" : "RNQFBKGPZ4M18PLZJA4BDGC32W",
"isCompleted" : true,
"percentComplete" : "100",
"card" : {
"id" : "1000000000000098718",
"bin" : "451129",
"proxyCardNumber" : "603953510161946xxxx",
"isActive" : false,
"isRegistered" : false,
"expirationDate" : "2017-06-30T23:59:59.000+0000",
"serviceCode" : "121",
"balances" : {
"openingBalance" : "5000",
"closingBalance" : "5000",
"pendingBalance" : "5000",
"currencyCode" : "USD"
},
"status" : "OPEN",
"statusReason" : "NONE",
"provisionType" : "PHYSICAL",
"accountStatus" : "OPEN",
"accountStatusReason" : "NONE",
"product" : {
"id" : "1000000000000000415",
"name" : "EXM Visa Corp LAP",
"isActive" : "true",
"productIdentifier" : "07675023660",
"bin" : "451129",
"issuer" : "MetaBank"
}
}
}
Below is the class GetCardInfo
public class GetCardInfo {
#XmlElement(name = "transactionId", required = true)
public String transactionId;
#XmlElement(name = "isCompleted", required = true)
public Boolean isCompleted;
#XmlElement(name = "percentComplete", required = true)
public String percentComplete;
#XmlElement(name = "card", required = true)
public Card card; //Parent for remaining data
public static class Card {
#XmlElement(name = "id", required = true)
public String id;
#XmlElement(name = "bin", required = true)
public String bin;
#XmlElement(name = "proxyCardNumber", required = true)
public String proxyCardNumber;
#XmlElement(name = "isActive", required = true)
public Boolean isActive;
#XmlElement(name = "isRegistered", required = true)
public Boolean isRegistered;
#XmlElement(name = "expirationDate", required = true, type = String.class)
#XmlJavaTypeAdapter(Adapter1 .class)
#XmlSchemaType(name = "dateTime")
public Date expirationDate;
#XmlElement(name = "serviceCode", required = true)
public String serviceCode;
#XmlElement(name = "balances", required = true)
public Balances balances; //Parent for balances data
#XmlElement(name = "status", required = true)
public String status;
#XmlElement(name = "statusReason", required = true)
public String statusReason;
#XmlElement(name = "provisionType", required = true)
public String provisionType;
#XmlElement(name = "accountStatus", required = true)
public String accountStatus;
#XmlElement(name = "accountStatusReason", required = true)
public String accountStatusReason;
#XmlElement(name = "product", required = true)
public Product product;
#Override
public String toString() {
return "Card [id=" + id + ", bin=" + bin + ", "
+ "proxyCardNumber=" + proxyCardNumber + ", isActive=" + isActive
+ ", isRegistered=" + isRegistered + ", expirationDate=" + expirationDate
+ ", serviceCode=" + serviceCode + ", balances=" + balances
+ ", status=" + status + ", statusReason=" + statusReason
+ ", provisionType=" + provisionType + ", accountStatus=" + accountStatus
+ ", accountStatusReason=" + accountStatusReason + ", product=" + product + "]";
}
}
public static class Balances {
#XmlElement(name = "openingBalance", required = true)
public String openingBalance;
#XmlElement(name = "closingBalance", required = true)
public String closingBalance;
#XmlElement(name = "pendingBalance", required = true)
public String pendingBalance;
#XmlElement(name = "currencyCode", required = true)
public String currencyCode;
#Override
public String toString() {
return "Balance [openingBalance=" + openingBalance + ", closingBalance=" + closingBalance + ", "
+ "pendingBalance=" + pendingBalance + ", currencyCode=" + currencyCode + "]";
}
}
public static class Product {
#XmlElement(name = "id", required = true)
public String id;
#XmlElement(name = "name", required = true)
public String name;
#XmlElement(name = "isActive", required = true)
public String isActive;
#XmlElement(name = "productIdentifier", required = true)
public String productIdentifier;
#XmlElement(name = "bin", required = true)
public String bin;
#XmlElement(name = "issuer", required = true)
public String issuer;
#Override
public String toString() {
return "Card [id=" + id + ", bin=" + bin + ", "
+ "name=" + name + ", isActive=" + isActive
+ ", productIdentifier=" + productIdentifier + ", issuer=" + issuer + "]";
}
}
#Override
public String toString() {
return "GetCardInfo [transactionId=" + transactionId
+ ", isCompleted=" + isCompleted
+ ", percentComplete=" + percentComplete
+ ", card=" + card + "]";
}
}
EDIT:
I put a catch block for IOException and found that I am getting below IOException. This would mean that there is something wrong with my JSON String.
Added my POM.xml below. Also added imports above for the Java file that has the ObjectMapper.
catch (IOException e) {
logger.error(
"IOException - ",
e.getMessage());
e.printStackTrace();
}
IOException - com.ctc.wstx.exc.WstxUnexpectedCharException: Unexpected character '{' (code 123) in prolog; expected '<'
at [row,col {unknown-source}]: [1,1]
Pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<organization>
<name>xxx</name>
<url></url>
</organization>
<parent>
<groupId>com.bhn.poms</groupId>
<artifactId>component-parent-pom</artifactId>
<version>2.17</version>
<relativePath />
</parent>
<artifactId>ivr-wrapper-service</artifactId>
<groupId>com.bhn.webservice</groupId>
<version>1.2.26-SNAPSHOT</version>
<name>IVR Wrapper Service Implementation</name>
<description>This project defines the java implementation for this service.</description>
<properties>
<bhn-entity-management-version>2.32</bhn-entity-management-version>
</properties>
<dependencies>
<dependency>
<groupId>com.bhn.webservice</groupId>
<artifactId>entity-management-service</artifactId>
<version>${bhn-entity-management-version}</version>
</dependency>
<dependency>
<groupId>com.bhn.webservice</groupId>
<artifactId>ivr-wrapper-domain-model</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.bhn.webservice</groupId>
<artifactId>web-service-client</artifactId>
<version>2.41</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>fluent-hc</artifactId>
<version>4.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.6.3</version>
</dependency>
<dependency>
<groupId>org.codehaus.woodstox</groupId>
<artifactId>woodstox-core-asl</artifactId>
<version>4.4.1</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20160212</version>
</dependency>
</dependencies>
<scm>
<connection>scm:git:ssh://git#xxx.com:7999/custom/ivrwrapper.git</connection>
<developerConnection>scm:git:ssh://git#xxx.com:7999/custom/ivrwrapper.git</developerConnection>
<tag>HEAD</tag>
</scm>
</project>
EDIT: based on #minus comment I have converted my JSON string to an XML string as below
JSONObject json = new JSONObject(JSONResponse.toString());
xml = XML.toString(json);
logger.info("GetCardInfo XML Response for KPN API: {} ", xml);
The log shows that it got converted to XML successfully.
<percentComplete>100</percentComplete><transactionId>FL2YTNR86KARMVYWWVK3410F4W</transactionId><card><product><productIdentifier>07675023660</productIdentifier><bin>451129</bin><name>EXM Visa Corp LAP</name><id>1000000000000000415</id><isActive>true</isActive><issuer>MetaBank</issuer></product><serviceCode>121</serviceCode><bin>451129</bin><isActive>false</isActive><proxyCardNumber>6039535101619469382</proxyCardNumber><accountStatusReason>NONE</accountStatusReason><accountStatus>OPEN</accountStatus><balances><pendingBalance>5000</pendingBalance><closingBalance>5000</closingBalance><openingBalance>5000</openingBalance><currencyCode>USD</currencyCode></balances><statusReason>NONE</statusReason><provisionType>PHYSICAL</provisionType><isRegistered>false</isRegistered><id>1000000000000098718</id><expirationDate>2017-06-30T23:59:59.000+0000</expirationDate><status>OPEN</status></card><isCompleted>true</isCompleted>
Next I am using below code to deserialize the XML String back to the Java object. But the deserialize is not working.
GetCardInfo gci = mapper.readValue(xml, GetCardInfo.class);
logger.info("Test12 ", gci.toString());
Now I don't get any error but Deserialization did not work. The fields in GCI object are null.
I'm not big at Jackson but you are trying to deserialize a json document with an XML mapper.
Jackson is telling you exactly that, you can't start an xml with '{'.
You should use a JsonMapper to deserialize Json and then an XMLMapper to serialize it.
I don't know if it is possible annotating the same class for both.
Thanks to #minus for his input.
I was able to figure out answer
all I needed was to add the classname to my XML string as below
String input = "" + xml + "";
After that I was able to deserialize successfully.

JPQL query in Spring data jpa

Lets say we have :
class Range {
public long start;
public long end;
}
This JPA entity:
#Entity
#Table(name="entry")
public class Entry {
#Id
long id;
#OneToMany
Set<Individual> individuals;
}
another JPA entity:
#Entity
#Table(name="individual")
public class Individual {
#Id
long id;
long code;
#ManyToOne
Entry entry;
}
and a controller:
public class IndexedEntryController {
EntityManagerFactory emf;
List<Entry> find(List<Range> lst) {
String str = "";
for(Range r:lst) {
if(!str.isEmpty) {
str += " or ";
}
str += "(i.code between " + r.start + " and " + r.end + ")";
}
String query = "Select i.entry from Individual i where " + str + " group by i.entry having count(i) > " + lst.size()-1;
EntityManager em = emf.createEntityManager();
return em.createQuery(query).getResultList();
}
}
This query returns all entries that have n-1 individuals with code between one of specific ranges, where n is number of ranges.
I want to move to Spring JpaRepository. How can I implement this query with a JpaRepository?

Categories

Resources