BLOB as parameter in procedure call in mybatis - mybatis

This is the call in the ProductServices.xml
<update id="resetPassword" parameterType="batchReport">
{ call user_account_mng.enc_reset_password(
#{user_Id,jdbcType=VARCHAR,mode=IN},
#{encrypted_password,jdbcType=VARCHAR,mode=IN},
#{usr_id, dbcType=VARCHAR,mode=IN},
#{salt,jdbcType=VARCHAR,mode=IN},
#{ret_code,jdbcType=CHAR,mode=OUT},
#{pgp_encrypted_password,jdbcType=BLOB,mode=IN}
)}
Now BatchReport is a POJO:
(i have declared an alias for it as batchReport)
public class BatchReport
{
private String user_Id;
private String encrypted_password;
private String usr_id;
private String salt;
private String ret_code;
private byte[] pgp_encrypted_password;
public String getUser_Id() {
return user_Id;
}
public void setUser_Id(String user_Id) {
this.user_Id = user_Id;
}
public String getEncrypted_password() {
return encrypted_password;
}
public void setEncrypted_password(String encrypted_password) {
this.encrypted_password = encrypted_password;
}
public String getUsr_id() {
return usr_id;
}
public void setUsr_id(String usr_id) {
this.usr_id = usr_id;
}
public String getSalt() {
return salt;
}
public void setSalt(String salt) {
this.salt = salt;
}
public String getRet_code() {
return ret_code;
}
public void setRet_code(String ret_code) {
this.ret_code = ret_code;
}
public byte[] getPgp_encrypted_password() {
return pgp_encrypted_password;
}
public void setPgp_encrypted_password(byte[] pgp_encrypted_password) {
this.pgp_encrypted_password = pgp_encrypted_password;
}
}
My main class is like this :
<BatchReport batchReport = new BatchReport();
byte[] byteArray =new byte[]{1,2,3};
batchReport.setUser_Id("CHI");
batchReport.setEncrypted_password("97D6B45");
batchReport.setSalt("71L");
batchReport.setPgp_encrypted_password(byteArray);
String returnCode = productServiceObj.resetPassword(batchReport);
i am getting following error:
Error setting null parameter. Most JDBC drivers require that the JdbcType must be specified for all nullable parameters. Cause: java.sql.SQLException: Invalid column type
The error may involve com.example.services.ProductServices.resetPassword-Inline
ProductServices is a class in which the method resetPassword is declared.
Please help me with this BLOB issue.
What should be the jdbcType in the called procedure.
what value should be passed in this pgp_encrypted_password.

Okay I found the solution to the problem now the jdbcType in the query in .xml file remains the same i.e BLOB.
Next the type which gets set for passing in the values is byte[].
So everything remains same as i have covered up .
Error actually existed as the in .xml file returns an integer indicating the number of rows changed in query and I have given the function return type as String so here goes the solution for the problem it should be of type Object.

Related

Quarkus PanacheMongoEntity - Is there no automatic encoding/decoding of Enum?

This is my Entity "WebhookType":
public class WebhookType extends PanacheMongoEntity {
public ObjectId id;
public String type;
public String name;
public String description;
public String image;
public List<WebhookTypeParameter> webhookTypeParameters = new ArrayList<>();
}
Which is having a list of "WebhookTypeParameters":
public class WebhookTypeParameter {
public Enum<ParameterType> parameterType;
public String parameterName;
public String parameterExample;
public WebhookTypeParameter(){
}
public Enum<ParameterType> getParameterType() {
return parameterType;
}
public void setParameterType(Enum<ParameterType> parameterType) {
this.parameterType = parameterType;
}
public String getParameterName() {
return parameterName;
}
public void setParameterName(String parameterName) {
this.parameterName = parameterName;
}
public String getParameterExample() {
return parameterExample;
}
public void setParameterExample(String parameterExample) {
this.parameterExample = parameterExample;
}
public WebhookTypeParameter(String parameterName, Enum<ParameterType>parameterType, String parameterExample){
this.setParameterName(parameterName);
this.setParameterType(parameterType);
this.setParameterExample(parameterExample);
}
}
Which are having a field "parameterType" of Type Enum:
public enum ParameterType {
STRING, DOUBLE;
}
Now when trying to persist my entity like this:
WebhookType webhookType = new WebhookType();
webhookType.type = "XYZ";
webhookType.name = "XYZ";
webhookType.image = "image url";
webhookType.description = ("Lorem Ipsum");
webhookType.webhookTypeParameters.add(new WebhookTypeParameter("title", ParameterType.STRING, "titel xy"));
webhookType.webhookTypeParameters.add(new WebhookTypeParameter("name", ParameterType.STRING, "foobar"));
webhookType.persist();
I get this in my log:
2020-09-19 14:01:07,587 ERROR [io.qua.application] (Quarkus Main Thread) Failed to start application: org.bson.codecs.configuration.CodecConfigurationException: An exception occurred when encoding using the AutomaticPojoCodec.
Encoding a WebhookType: 'WebhookType<null>' failed with the following exception:
Failed to encode 'WebhookType'. Encoding 'webhookTypeParameters' errored with: An exception occurred when encoding using the AutomaticPojoCodec.
Encoding a WebhookTypeParameter: 'x.x.x.WebhookTypeParameter#474d3e58' failed with the following exception:
Failed to encode 'WebhookTypeParameter'. Encoding 'parameterType' errored with: Can't find a codec for class x.x.x.ParameterType.
A custom Codec or PojoCodec may need to be explicitly configured and registered to handle this type.
So my question is what's wrong with my enum and why is it not automatically encoded?

Trying to read values returned on jsp form submission in springboot project by setters and use the combination to call another java class

So, I have values in getter setter variables when I click on form submit but now want to have those values in variables and check combination of them to run code from another java class
I have tried using parametrized constructor or may be having a common setter but that did not help.
package com.grt.dto;
import java.util.Set;
public class WDPayrollRecon {
public Set<String> dataType;
public String planCountry;
public String payPeriod;
public String currentPeriod;
public String lastPayPeriod;
Set<String> test;
public Set<String> getdataType() {
return dataType;
}
public void setdataType(Set<String> dataType) {
this.dataType = dataType;
System.out.println("this is dataType" +dataType);
test = dataType;
}
public String getPlanCountry() {
return planCountry;
}
public void setPlanCountry(String planCountry) {
this.planCountry = planCountry;
}
public String getPayPeriod() {
return payPeriod;
}
public void setPayPeriod(String payPeriod) {
this.payPeriod = payPeriod;
}
public String getCurrentPeriod() {
return currentPeriod;
}
public void setCurrentPeriod(String currentPeriod) {
this.currentPeriod = currentPeriod;
}
public String getlastPayPeriod() {
return lastPayPeriod;
}
public void setlastPayPeriod(String lastPayPeriod) {
this.lastPayPeriod = lastPayPeriod;
}
public WDPayrollRecon()
{
}
public WDPayrollRecon(Set<String> dataType,String planCountry,String payPeriod,String currentPeriod,String lastPayPeriod)
{
this.dataType = dataType;
this.planCountry = planCountry;
this.payPeriod = payPeriod;
this.currentPeriod = currentPeriod;
this.lastPayPeriod = lastPayPeriod;
if(dataType.contains("GTLI")& planCountry.equals("USA")){
System.out.println("This is test");
}
else{
System.out.println("This is not test");
}
}
}

JPA2.0 property access in spring rest data -- some getters not being called

I am still somewhat of a novice with Spring Boot and Spring Data Rest and hope someone out there with experience in Accessing by Property. Since I cannot change a database which stores types for Letters in an unnormalized fashion (delimited string in a varchar), I thought that I could leverage some logic in properties to overcome this. However I notice that when using property access, some of my getters are never called.
My Model code:
package ...
import ...
#Entity
#Table(name="letters", catalog="clovisdb")
#Access(AccessType.PROPERTY)
public class Letter {
public enum PhoneticType {
VOWEL, SHORT, LONG, COMMON;
public static boolean contains(String s) { ... }
}
public enum PositionType {
ALL, INITIAL, MEDIAL, FINAL;
public static boolean contains(String s) { ... }
}
public enum CaseType {
ALL, LOWER, UPPER;
public static boolean contains(String s) { ... }
}
private int id;
private String name;
private String translit;
private String present;
private List<PhoneticType> phoneticTypes;
private CaseType caseType;
private PositionType positionType;
#Id
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getTranslit() { return translit; }
public void setTranslit(String translit) { this.translit = translit; }
public String getPresent() { return present; }
public void setPresent(String present) { this.present = present; }
public String getTypes() {
StringBuilder sb = new StringBuilder(); //
if (phoneticTypes!=null) for (PhoneticType type : phoneticTypes) sb.append(" ").append(type.name());
if (caseType!=null) sb.append(" ").append(caseType.name());
if (positionType!=null) sb.append(" ").append(positionType.name());
return sb.substring( sb.length()>0?1:0 );
}
public void setTypes(String types) {
List<PhoneticType> phoneticTypes = new ArrayList<PhoneticType>();
CaseType caseType = null;
PositionType positionType = null;
for (String val : Arrays.asList(types.split(" "))) {
String canonicalVal = val.toUpperCase();
if (PhoneticType.contains(canonicalVal)) phoneticTypes.add(PhoneticType.valueOf(canonicalVal));
else if (CaseType.contains(canonicalVal)) caseType = CaseType.valueOf(canonicalVal);
else if (PositionType.contains(canonicalVal)) positionType = PositionType.valueOf(canonicalVal);
}
this.phoneticTypes = phoneticTypes;
this.caseType = (caseType==null)? CaseType.ALL : caseType;
this.positionType = (positionType==null)? PositionType.ALL : positionType;
}
#Override
public String toString() { .... }
}
My Repository/DAO code:
package ...
import ...
#RepositoryRestResource
public interface LetterRepository extends CrudRepository<Letter, Integer> {
List<Letter> findByTypesLike(#Param("types") String types);
}
Hitting this URI: http://mytestserver.com:8080/greekLetters/6
and setting breakpoints on all the getters and setters, I can see that the properties are called in this order:
setId
setName
setPresent
setTranslit
setTypes
(getId not called)
getName
getTranslit
getPresent
(getTypes not called !!)
The json returned for the URI above reflects all the getters called, and there are no errors
{
"name" : "alpha",
"translit" : "`A/",
"present" : "Ἄ",
"_links" : {
"self" : {
"href" : "http://mytestserver.com:8080/letters/6"
}
}
}
But why is my getTypes() not being called and my JSON object missing the “types” attribute? I note that the setter is called, which makes it even stranger to me.
Any help would be appreciated!
Thanks in advance
That's probably because you don't have a field types, so getTypes() isn't a proper getter. Try adding this to your entity
#Transient
private String types;
I don't know how the inner works, but it's possible that the class is first scanned for its fields, and then a getter is called for each field. And since you don't have types field, the getter isn't called. Setter getting called could be a feature but I wouldn't be surprised if it is a bug, because findByTypesLike should translate to find Letters whose types field is like <parameter>, and types is not a field.
Another thing you can try, is to annotate that getter with #JsonInclude. Jackson 2 annotations are supported in Spring versions 3.2+ (also backported to 3.1.2).

JPA, How to find an object that has composite id?

Based on second approach answered here I designed my JPA class.
#Entity(name = "SearchKeywordJPA")
#IdClass(SearchKeywordJPA.SearchKeyId.class)
public class SearchKeywordJPA implements Comparable<SearchKeywordJPA> {
#Id
private String keyword;
#Id
private long date;
private String userUUID;
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SearchKeywordJPA that = (SearchKeywordJPA) o;
if (date != that.date) return false;
if (!keyword.equals(that.keyword)) return false;
if (!userUUID.equals(that.userUUID)) return false;
return true;
}
#Override
public int hashCode() {
int result = keyword.hashCode();
result = 31 * result + (int) (date ^ (date >>> 32));
result = 31 * result + userUUID.hashCode();
return result;
}
#Override
public String toString() {
return "SearchKeywordJPA{" +
"keyword='" + keyword + '\'' +
", date=" + date +
", userUUID='" + userUUID + '\'' +
'}';
}
public String getKeyword() {
return keyword;
}
public void setKeyword(String keyword) {
this.keyword = keyword;
}
public long getDate() {
return date;
}
public void setDate(long date) {
this.date = date;
}
public String getUserUUID() {
return userUUID;
}
public void setUserUUID(String userUUID) {
this.userUUID = userUUID;
}
#Override
public int compareTo(SearchKeywordJPA searchRecord) {
long comparedDate = searchRecord.date;
if (this.date > comparedDate) {
return 1;
} else if (this.date == comparedDate) {
return 0;
} else {
return -1;
}
}
/**********************
* Key class
**********************/
public class SearchKeyId {
private int id;
private int version;
}
}
In my servlet I want to check datastore and store my object if is not exist.
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
...
for(SearchKeywordJPA item: applicationList) {
if(!isRecorded(item))
storeRecord(item);
}
}
private boolean isRecorded(SearchKeywordJPA record) {
EntityManager em = EMF.get().createEntityManager();
SearchKeywordJPA item = em.find(SearchKeywordJPA.class, record);
return item != null;
}
private void storeRecord(SearchKeywordJPA record) {
EntityManager em = EMF.get().createEntityManager();
em.persist(record);
}
However when I run, application crashes and log says
javax.persistence.PersistenceException: org.datanucleus.store.appengine.FatalNucleusUserException: Received a request to find an object of type com.twitterjaya.model.SearchKeywordJPA identified by SearchKeywordJPA{keyword='airasia', date=1335680686149, userUUID='FFFF0000'}. This is not a valid representation of a primary key for an instance of com.twitterjaya.model.SearchKeywordJPA.
What is the reason? any suggestion would be appreciated. Thanks
You pass an instance of the IdClass into em.find ... i.e SearchKeyId. Obviously if you really have an IdClass that has no equals/hashCode/toString/constructor then you will likely get many problems. Those problems will only be increased by using an ancient plugin for GAE/Datastore.
If your Key is
#Entity(name = "SearchKeywordJPA")
#IdClass(SearchKeywordJPA.SearchKeyId.class)
public class SearchKeywordJPA implements Comparable<SearchKeywordJPA> {
you are doing it wrong.
IdClass does not need any annotation of #IdClass just the #Id
annotation.
Key can not be an entity.
Need to implements Serializable , comparable is not needed
Need to override equals and hascode and have no arg constructor
Class key need to be as follows.
public class SearchKeyId implements Serializable {
private String keyword;
private long date;
And your entity I assume something like this.
#Entity(name = "SearchKeywordJPA")
#IdClass(SearchKeyId.class)
public class SearchKeywordJPA {
#Id
private String keyword;
#Id
private long date;
private String userUUID;
Just consider that find method will use the SearchKey.class to find
the entities.
Fields that are in the IdClass need to have #Id annotation in the entity.
Key can not be an entity on its own.
Comparable is not really needed as all the comparison are placed in the IdClass

Spring List Binding

Thanks in advance for any help.
I have the following object association in my model:
public class Contract {
private Integer id;
private String name;
//getters/setters...
}
public class User {
....
private List<Contract> contracts;
....
}
Controller:
#RequestMapping(....)
public String getUser(#PathVariable Integer userId, Model model) {
....
model.addAttribute(userDao.findUser(userId));
model.addAttribute("contractsList", contractDao.findAllContracts());
....
}
#RequestMapping(....)
public String processUser(#ModelAttribute User user, Model model) {
....
//Create a copy of the user to update...
User userToUpdate = userDao.findUser(user.getId);
....
userToUpdate.setContracts(user.getContracts());
//set other properties...
userDao.updateUser(userToUpdate);
return "someSuccessView";
}
#InitBinder
protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
binder.registerCustomEditor(Contract.class, new UserContractsPropertyEditor());
}
My PropertyEditor:
public class UserContractsPropertyEditor extends PropertyEditorSupport {
#Inject ContractDao contractDao;
#Override
public void setAsText(String text) throws IllegalArgumentException {
System.out.println("matching value: " + text);
if (text != "") {
Integer contractId = new Integer(text);
super.setValue(contractDao.findContract(contractId));
}
}
}
My JSP form:
<form:form commandName="user">
<%-- Other fields... --%>
<form:checkboxes items="${contractsList}"
path="contracts"
itemValue="id"
itemLabel="name" />
</form:form>
The form renders correctly. That is, the checkbox list of Contracts is generated and the correct ones are "checked." The problem is when I submit I get:
java.lang.IllegalArgumentException: 'items' must not be null
at org.springframework.util.Assert.notNull(Assert.java:112)
at org.springframework.web.servlet.tags.form.AbstractMultiCheckedElementTag.setItems(AbstractMultiCheckedElementTag.java:83)
at org.apache.jsp.WEB_002dINF.jsp._005fn.forms.user_jsp._jspx_meth_form_005fcheckboxes_005f0(user_jsp.java:1192)
....
The custom property editor seems to be doing its job and there are no null/empty strings being passed.
If the form and controller makes the conversion when viewing the form, why is it having trouble when processing the form? What am I missing here?
You need to ensure that a call to getContract() returns a List instance:
public List<Contract> getContracts() {
if (contracts == null) contracts = new ArrayList<Contract>();
return contracts;
}
Thanks for your response. I guess a fresh set of eyes first thing in the morning does the trick again.
Apparently, my custom property editor had no clue what to do with the id value I was passing in since it couldn't access my DAO/service. So, I had to change the constructor:
public class UserContractsPropertyEditor extends PropertyEditorSupport {
private ContractDao contractDao;
public UserContractsPropertyEditor(ContractDao contractDao) {
this.contractDao = contractDao;
}
#Override
public void setAsText(String text) throws IllegalArgumentException {
Integer contractId = new Integer(text);
Contract contract = contractDao.findContract(contractId);
super.setValue(contract);
}
}
Then, modified the initBinder in my controller:
#Inject ContractDao contractDao;
....
#InitBinder
protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
binder.registerCustomEditor(Contract.class, new UserContractsPropertyEditor(this.contractDao));
}
Maybe this will help someone else.