Encryption in Java 7 - encryption

In Java 7, I want to do Encryption and Decryption of a password by using
SHA-256 and AES-256.
I tried to use PBKDF2WithHmacSHA256, but this is unsupported in Java7.
Do you have any ideas? Please tell me the Library information.
Thanks.
Example(Java8)
public class PasswordUtil {
private static final String ALGORITHM = "PBKDF2WithHmacSHA256";
private static final int ITERATION_COUNT = 10000;
private static final int KEY_LENGTH = 256;
/**
*
* #param password
* #param salt
* #return
*/
public static String getSafetyPassword(String password, String salt) {
char[] passCharAry = password.toCharArray();
byte[] hashedSalt = getHashedSalt(salt);
PBEKeySpec keySpec = new PBEKeySpec(passCharAry, hashedSalt, ITERATION_COUNT, KEY_LENGTH);
SecretKeyFactory skf;
try {
skf = SecretKeyFactory.getInstance(ALGORITHM);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
SecretKey secretKey;
try {
secretKey = skf.generateSecret(keySpec);
} catch (InvalidKeySpecException e) {
throw new RuntimeException(e);
}
byte[] passByteAry = secretKey.getEncoded();
StringBuilder sb = new StringBuilder(64);
for (byte b : passByteAry) {
sb.append(String.format("%02x", b & 0xff));
}
return sb.toString();
}
/**
*
* #param salt
* #return
*/
private static byte[] getHashedSalt(String salt) {
MessageDigest messageDigest;
try {
messageDigest = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
messageDigest.update(salt.getBytes());
return messageDigest.digest();
}
}

Encryption and Decryption of a password by using AES in JAVA 7
Encryptionsss.java ::
public class Encryptionsss {
public static void main(String[] args) throws Exception {
try {
String text = "Hello World";
String key = "1234567891234567";
// Create key and cipher
Key aesKey = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
// encrypt the text
cipher.init(Cipher.ENCRYPT_MODE, aesKey);
byte[] encrypted = cipher.doFinal(text.getBytes());
System.out.println("Encrypted text: " + new String(encrypted));
// decrypt the text
cipher.init(Cipher.DECRYPT_MODE, aesKey);
String decrypted = new String(cipher.doFinal(encrypted));
System.out.println("Decrypted text: " + decrypted);
}catch(Exception e) {
e.printStackTrace();
}
String plainText = "Hello World";
/**
* Generate new Key
*/
// String str = generatenewkeyasString();
/*** Generate Cipher Text from Key(We are using same key stored in String-str)
****/
String str = "]˜??4I-S#æ,Ôt";
byte[] data = str.getBytes();
SecretKey key2 = new SecretKeySpec(data, 0, data.length, "AES");
byte[] cipherText = encryptText(plainText, key2);
String scipherText = new String(cipherText);
/**
*
* Decrypt Cipher Text with Key****/
cipherText = scipherText.getBytes();
String decryptedText = decryptText(cipherText, key2);
System.out.println("ScipherText:" + scipherText);
System.out.println("Original Text:" + plainText);
System.out.println("AES Key (Hex Form):"
+ bytesToHex(key2.getEncoded()));
System.out.println("Encrypted Text (Hex Form):"
+ bytesToHex(cipherText));
System.out.println("Descrypted Text:" + decryptedText);
}
/**
*
* #return byte[] as String
* #Generate Key
*/
private static String generatenewkeyasString() throws Exception {
SecretKey secKey = KeyGenerator.getInstance("AES").generateKey();
byte[] data = secKey.getEncoded();
String str = new String(data);
return str;
}
/**
*
* Encrypts plainText in AES using the secret key
*
* #param plainText
*
* #param secKey
*
* #return
*
* #throws Exception
*/
public static byte[] encryptText(String plainText, SecretKey secKey)
throws Exception {
// AES defaults to AES/ECB/PKCS5Padding in Java 7
Cipher aesCipher = Cipher.getInstance("AES");
aesCipher.init(Cipher.ENCRYPT_MODE, secKey);
byte[] byteCipherText = aesCipher.doFinal(plainText.getBytes());
return byteCipherText;
}
/**
*
* Decrypts encrypted byte array using the key used for encryption.
*
* #param byteCipherText
* #param secKey
*
* #return
*
* #throws Exception
*/
public static String decryptText(byte[] byteCipherText, SecretKey secKey)
throws Exception {
// AES defaults to AES/ECB/PKCS5Padding in Java 7
Cipher aesCipher = Cipher.getInstance("AES");
aesCipher.init(Cipher.DECRYPT_MODE, secKey);
byte[] bytePlainText = aesCipher.doFinal(byteCipherText);
return new String(bytePlainText);
}
/**
*
* Convert a binary byte array into readable hex form
*
* #param hash
*
* #return
*/
private static String bytesToHex(byte[] hash) {
return DatatypeConverter.printHexBinary(hash);
}
}

Related

Can we set the disable conversion value from config in #Converter

#Convert(converter = MsisdnEncryptor.class,disableConversion=true)
I have used this converter in my spring boot entity class.
package com.example.demo.entity;
This is the entity class:
#Entity
#Data
#AllArgsConstructor
#NoArgsConstructor
#Table(name="employee")
public class Employee {
#Id
#Column(name = "emp_id")
#SequenceGenerator(
name = "employee_sequence",
sequenceName = "employee_sequence",
allocationSize = 1
)
#GeneratedValue(strategy = GenerationType.SEQUENCE,
generator = "employee_sequence")
private Long EmpId;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Column(name = "mobile_number")
**#Convert(converter = MsisdnEncryptor.class,disableConversion=true)**
**here I want to put values from application.properties in disableConversion**
private String mobileNumber;
#Column(name= "date_time")
#JsonFormat(shape=JsonFormat.Shape.STRING, pattern="dd-MM-yyyy HH:mm:ss", timezone="GMT+5:30")
private Timestamp dateTime;
}
This is the Encryptor class:
#Component
public class MsisdnEncryptor implements AttributeConverter<String, String> {
private static final Logger logger = LoggerFactory.getLogger(MsisdnEncryptor.class);
#Value("${is.enabled:true}")
private boolean isEnabled;
private static final String AES = "AES";
private static final String SECRET = "secret-key-12345";
private final Key key;
private final Cipher cipher;
public MsisdnEncryptor() throws Exception {
key = new SecretKeySpec(SECRET.getBytes(), AES);
cipher = Cipher.getInstance(AES);
}
#Override
public String convertToDatabaseColumn(String attribute) {
try {
cipher.init(Cipher.ENCRYPT_MODE, key);
return Base64.getEncoder().encodeToString(cipher.doFinal(attribute.getBytes()));
} catch (IllegalBlockSizeException | BadPaddingException | InvalidKeyException e) {
throw new IllegalStateException(e);
}
}
#Override
public String convertToEntityAttribute(String dbData) {
try {
cipher.init(Cipher.DECRYPT_MODE, key);
return new String(cipher.doFinal(Base64.getDecoder().decode(dbData)));
} catch (InvalidKeyException | BadPaddingException | IllegalBlockSizeException e) {
throw new IllegalStateException(e);
}
}
}
I know we can use #Value for taking the values , but it doesn't work here as it says attribute value must be constant.
Or if there is any other way of doing the encryption and enabling/disabling it from config , I would be more than happy to go through it.

Spring MVC: 400 bad request The request sent by the client was syntactically incorrect

Please help to check this method. I got error http status 400 when I tried to post data using postman. Is there any mistake in this method?
#RequestMapping(value = "/Timestamp", method = RequestMethod.POST)
#ResponseBody
public Timestamp newTimestamp(#RequestBody Timestamp timestamp) {
System.out.println("Test: "+ timestamp);
timestampService.saveTimestamp(timestamp);
return timestampDAO.findTimestampByPrimaryKey(timestamp.getId());
}
And This is my Timestamp class:
package ehealth.domain;
import java.io.Serializable;
import java.lang.StringBuilder;
import java.util.Calendar;
import java.util.LinkedHashSet;
import java.util.Set;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import org.codehaus.jackson.annotate.JsonIgnore;
import javax.xml.bind.annotation.*;
import javax.persistence.*;
/**
*/
#Entity
#NamedQueries({
#NamedQuery(name = "findAllTimestamps", query = "select myTimestamp from Timestamp myTimestamp"),
#NamedQuery(name = "findTimestampByCreateDate", query = "select myTimestamp from Timestamp myTimestamp where myTimestamp.createDate = ?1"),
#NamedQuery(name = "findTimestampById", query = "select myTimestamp from Timestamp myTimestamp where myTimestamp.id = ?1"),
#NamedQuery(name = "findTimestampByIsActive", query = "select myTimestamp from Timestamp myTimestamp where myTimestamp.isActive = ?1"),
#NamedQuery(name = "findTimestampByLoginDate", query = "select myTimestamp from Timestamp myTimestamp where myTimestamp.loginDate = ?1"),
#NamedQuery(name = "findTimestampByLogoutDate", query = "select myTimestamp from Timestamp myTimestamp where myTimestamp.logoutDate = ?1"),
#NamedQuery(name = "findTimestampByPrimaryKey", query = "select myTimestamp from Timestamp myTimestamp where myTimestamp.id = ?1"),
#NamedQuery(name = "findTimestampByUpdateDate", query = "select myTimestamp from Timestamp myTimestamp where myTimestamp.updateDate = ?1") })
#Table(catalog = "ehealthdb", name = "timestamp")
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(namespace = "eHealth_Backend/ehealth/domain", name = "Timestamp")
#XmlRootElement(namespace = "eHealth_Backend/ehealth/domain")
public class Timestamp implements Serializable {
private static final long serialVersionUID = 1L;
/**
*/
#Column(name = "id", nullable = false)
#Basic(fetch = FetchType.EAGER)
#Id
#XmlElement
Integer id;
/**
*/
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "login_date")
#Basic(fetch = FetchType.EAGER)
#XmlElement
Calendar loginDate;
/**
*/
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "logout_date")
#Basic(fetch = FetchType.EAGER)
#XmlElement
Calendar logoutDate;
/**
*/
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "create_date", nullable = false)
#Basic(fetch = FetchType.EAGER)
#XmlElement
Calendar createDate;
/**
*/
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "update_date")
#Basic(fetch = FetchType.EAGER)
#XmlElement
Calendar updateDate;
/**
*/
#Column(name = "isActive")
#Basic(fetch = FetchType.EAGER)
#XmlElement
Boolean isActive;
/**
*/
#OneToMany(mappedBy = "timestamp", cascade = { CascadeType.REMOVE }, fetch = FetchType.LAZY)
#XmlElement(name = "", namespace = "")
java.util.Set<ehealth.domain.User> users;
/**
*/
public void setId(Integer id) {
this.id = id;
}
/**
*/
public Integer getId() {
return this.id;
}
/**
*/
public void setLoginDate(Calendar loginDate) {
this.loginDate = loginDate;
}
/**
*/
public Calendar getLoginDate() {
return this.loginDate;
}
/**
*/
public void setLogoutDate(Calendar logoutDate) {
this.logoutDate = logoutDate;
}
/**
*/
public Calendar getLogoutDate() {
return this.logoutDate;
}
/**
*/
public void setCreateDate(Calendar createDate) {
this.createDate = createDate;
}
/**
*/
public Calendar getCreateDate() {
return this.createDate;
}
/**
*/
public void setUpdateDate(Calendar updateDate) {
this.updateDate = updateDate;
}
/**
*/
public Calendar getUpdateDate() {
return this.updateDate;
}
/**
*/
public void setIsActive(Boolean isActive) {
this.isActive = isActive;
}
/**
*/
public Boolean getIsActive() {
return this.isActive;
}
/**
*/
public void setUsers(Set<User> users) {
this.users = users;
}
/**
*/
#JsonIgnore
public Set<User> getUsers() {
if (users == null) {
users = new java.util.LinkedHashSet<ehealth.domain.User>();
}
return users;
}
/**
*/
public Timestamp() {
}
/**
* Copies the contents of the specified bean into this bean.
*
*/
public void copy(Timestamp that) {
setId(that.getId());
setLoginDate(that.getLoginDate());
setLogoutDate(that.getLogoutDate());
setCreateDate(that.getCreateDate());
setUpdateDate(that.getUpdateDate());
setIsActive(that.getIsActive());
setUsers(new java.util.LinkedHashSet<ehealth.domain.User>(that.getUsers()));
}
/**
* Returns a textual representation of a bean.
*
*/
public String toString() {
StringBuilder buffer = new StringBuilder();
buffer.append("id=[").append(id).append("] ");
buffer.append("loginDate=[").append(loginDate).append("] ");
buffer.append("logoutDate=[").append(logoutDate).append("] ");
buffer.append("createDate=[").append(createDate).append("] ");
buffer.append("updateDate=[").append(updateDate).append("] ");
buffer.append("isActive=[").append(isActive).append("] ");
return buffer.toString();
}
/**
*/
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = (int) (prime * result + ((id == null) ? 0 : id.hashCode()));
return result;
}
/**
*/
public boolean equals(Object obj) {
if (obj == this)
return true;
if (!(obj instanceof Timestamp))
return false;
Timestamp equalCheck = (Timestamp) obj;
if ((id == null && equalCheck.id != null) || (id != null && equalCheck.id == null))
return false;
if (id != null && !id.equals(equalCheck.id))
return false;
return true;
}
}
Json data using Postman
{
"id":4,
"loginDate":"01/30/2016 12:12:12 AM",
"logoutDate":"01/30/2016 12:12:12 AM",
"createDate":"01/30/2016 12:12:12 AM",
"updateDate":"01/30/2016 12:12:12 AM",
"isActive":true
}
look up is that the date formats I believe by default are expected to be ISO 8601 (looks like you are using codehaus for your json parsing). I suggest you look up how to define how a date is to be parsed or change your date format in the JSON if that is possible

passing in sql.oracle.ARRAY SimpleJdbcCall to StoredProcedure

I am using JBoss 7.1.Final as application server and Oracle as database. We are using Spring framework 3.x and Java 6. trying to pass in an array of Strings and convert them inside the stored proc to array of varchars. I haven't found a good example for this yet. Please provide a pointer if you can to any documentation or previous forum post. I have searched and not found one that seems to apply.
The stored proc is defined as:
CREATE OR REPLACE PROCEDURE GET_TEST_CONTENTS
(IN_RR_ARRAY IN RR_ARRAY,
IN_ORDER_STATE IN VARCHAR2,
OUT_FLAG OUT VARCHAR2,
OUT_RETURN_CODE OUT VARCHAR2,
OUT_RETURN_DESC OUT VARCHAR2,
OUT_RETURN_TYPE OUT VARCHAR2,
OUT_RETURN_VAL OUT NUMBER
)
Type RR_ARRAY is defined as:
create or replace
type RR_ARRAY as table of varchar2(15);
Within my java code I have:
jdbcTemplate = new JdbcTemplate(dataSource);
jdbcTemplate.setResultsMapCaseInsensitive(true);
this.getTestContents = new SimpleJdbcCall(jdbcTemplate)
.withCatalogName("STAR")
.withoutProcedureColumnMetaDataAccess()
.withProcedureName("GET_TEST_CONTENTS")
.declareParameters(
new SqlParameter("IN_RR_ARRAY", OracleTypes.ARRAY,
"RR_ARRAY"),
new SqlParameter("IN_ORDER_STATE", OracleTypes.VARCHAR), new SqlOutParameter("OUT_FLAG",
OracleTypes.VARCHAR),
new SqlOutParameter("OUT_RETURN_VAL", OracleTypes.INTEGER),
new SqlOutParameter("OUT_RETURN_CODE", OracleTypes.VARCHAR),
new SqlOutParameter("OUT_RETURN_DESC", OracleTypes.VARCHAR),
new SqlOutParameter("OUT_RETURN_TYPE", OracleTypes.VARCHAR));
//I get a different error here so creating new connection for testing
//conn = jdbcTemplate.getDataSource().getConnection();
Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
conn = DriverManager.getConnection(jdbcURL, user, passwd);
ArrayDescriptor desc = new ArrayDescriptor("STAR.RR_ARRAY", conn);
ARRAY arr = new ARRAY(desc, conn, testArray); // testArray is just
// String[] with 2 values
Map<String, Object> hm = new HashMap<String, Object>();
hm.put("IN_RR_ARRAY", arr);
hm.put("IN_ORDER_STATE", stateCode);
hm.put("OUT_FLAG", Types.VARCHAR);
hm.put("OUT_RETURN_CODE", Types.VARCHAR);
hm.put("OUT_RETURN_DESC", Types.VARCHAR);
hm.put("OUT_RETURN_TYPE", Types.VARCHAR);
SqlParameterSource in = new MapSqlParameterSource().addValues(hm);
Map out = getTestContents .execute(in);
The stack trace returned is:
11:24:43,691 ERROR [com.test.repository.TestContentsDao] (http-localhost-127.0.0.1-8080-1) Error while calling GET_TEST_CONTENTS Stored procedure: org.springframework.jdbc.UncategorizedSQLException: CallableStatementCallback; uncategorized SQLException for SQL [{call STAR.GET_TEST_CONTENTS(?, ?, ?, ?, ?, ?, ?)}]; SQL state [99999]; error code [17059]; Fail to convert to internal representation: oracle.sql.ARRAY#2a081f8f; nested exception is java.sql.SQLException: Fail to convert to internal representation: oracle.sql.ARRAY#2a081f8f
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:83) [spring-jdbc-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80) [spring-jdbc-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80) [spring-jdbc-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:969) [spring-jdbc-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.call(JdbcTemplate.java:1003) [spring-jdbc-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.jdbc.core.simple.AbstractJdbcCall.executeCallInternal(AbstractJdbcCall.java:388) [spring-jdbc-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.jdbc.core.simple.AbstractJdbcCall.doExecute(AbstractJdbcCall.java:351) [spring-jdbc-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.jdbc.core.simple.SimpleJdbcCall.execute(SimpleJdbcCall.java:181) [spring-jdbc-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at com.test.repository.TestContentsDao.isGood(TestContentsDao.java:147) [classes:]
Any advice or pointers to examples or docs will be appreciated
I found the fix for this. Now I use this List of Strings:
List<String> ndcList;
I changed the array parameter from OracleTypes.ARRAY to java.sql.stypes.ARRAY and specified schema prefix on array name. And changed the code and created a few new convenience methods at the bottom.
I needed the wrapped connection and had to add this dependency to my pom:
<dependency>
<groupId>jboss</groupId>
<artifactId>jboss-common-jdbc-wrapper</artifactId>
<version>3.2.3</version>
</dependency>
---- method code starts here------------
jdbcTemplate = new JdbcTemplate(dataSource);
jdbcTemplate.setResultsMapCaseInsensitive(true);
this.getTestContents = new SimpleJdbcCall(jdbcTemplate)
.withCatalogName("STAR")
.withoutProcedureColumnMetaDataAccess()
.withProcedureName("GET_TEST_CONTENTS")
.declareParameters(
new SqlParameter("IN_RR_ARRAY", java.sql.types.ARRAY, "STAR.RR_ARRAY"),
new SqlParameter("IN_ORDER_STATE", OracleTypes.VARCHAR),
new SqlOutParameter("OUT_FLAG", OracleTypes.VARCHAR),
new SqlOutParameter("OUT_RETURN_VAL", OracleTypes.INTEGER),
new SqlOutParameter("OUT_RETURN_CODE", OracleTypes.VARCHAR),
new SqlOutParameter("OUT_RETURN_DESC", OracleTypes.VARCHAR),
new SqlOutParameter("OUT_RETURN_TYPE", OracleTypes.VARCHAR));
Map<String, Object> hm = new HashMap<String, Object>();
hm.put("IN_RR_ARRAY", new ScriptArray(ndcList));
hm.put("IN_ORDER_STATE", stateCode);
hm.put("OUT_FLAG", Types.VARCHAR);
hm.put("OUT_RETURN_CODE", Types.VARCHAR);
hm.put("OUT_RETURN_DESC", Types.VARCHAR);
hm.put("OUT_RETURN_TYPE", Types.VARCHAR);
SqlParameterSource in = new MapSqlParameterSource().addValues(hm);
Map out = getTestContents.execute(in);
---- method code ends here------------
public class ScriptArray extends AbstractSqlTypeValue {
private List<String> values;
public ScriptArray(List<String> values) {
this.values = values;
}
public Object createTypeValue(Connection con, int sqlType,
String typeName) throws SQLException {
oracle.jdbc.OracleConnection wrappedConnection = con
.unwrap(oracle.jdbc.OracleConnection.class);
con = wrappedConnection;
ArrayDescriptor desc = new ArrayDescriptor(typeName, con);
return new ARRAY(desc, con,
(String[]) values.toArray(new String[values.size()]));
}
}
Been fighting the similar issue for a day. This article helped me.
Here's code backup, in case page will be unavailable:
-- custom type
create or replace TYPE "MY_TYPE"
as object(name varchar(255),
value varchar(255))
-- array of MY_TYPE
create or replace
TYPE "MY_ARRAY"
as table of MY_TYPE
-- echo like SP, doesn't do too much
create or replace
procedure foo(
i_array in MY_ARRAY,
o_array out MY_ARRAY)
as
begin
o_array := MY_ARRAY();
for i in 1 .. i_array.count loop
o_array.extend;
o_array(i) := MY_TYPE(i_array(i).name, i_array(i).value);
end loop;
end;
Java code:
public class FooStoredProcedure {
private static final String SP_NAME = "FOO";
private static final String MY_ARRAY = "MY_ARRAY";
private static final String MY_TYPE = "MY_TYPE";
private static final String I_ARRAY = "i_array";
private static final String O_ARRAY = "o_array";
private final StoredProcedure storedProcedure;
public FooStoredProcedure(DataSource dataSource) {
storedProcedure = new StoredProcedure(dataSource, SP_NAME) {
{
declareParameter(new SqlParameter(I_ARRAY, Types.ARRAY, MY_ARRAY));
declareParameter(new SqlOutParameter(O_ARRAY, Types.ARRAY, MY_ARRAY, new SqlReturnType() {
#Override
public Object getTypeValue(CallableStatement cs, int paramIndex,
int sqlType, String typeName) throws SQLException {
Connection connection = cs.getConnection();
Map<String, Class<?>> typeMap = connection.getTypeMap();
typeMap.put(MY_TYPE, MyType.class);
return cs.getObject(paramIndex);
}
}));
compile();
}
};
}
/**
* #return array of {#link MyType} objects or <code>null</code>
*/
public MyType[] execute(final MyType[] values) {
Map<String, Object> params = new HashMap<String, Object>();
params.put(I_ARRAY, new AbstractSqlTypeValue() {
#Override
protected Object createTypeValue(Connection con, int sqlType, String typeName) throws SQLException {
ArrayDescriptor descriptor = new ArrayDescriptor(typeName, con);
return new ARRAY(descriptor, con, values);
}
});
Map<?, ?> result = storedProcedure.execute(params);
if ((!result.containsKey(O_ARRAY) || result.get(O_ARRAY) == null)) {
return null;
}
try {
Object[] resultArray = (Object[]) ((ARRAY) result.get(O_ARRAY)).getArray();
return Arrays.copyOf(resultArray, resultArray.length, MyType[].class);
} catch (SQLException e) {
throw new DataRetrievalFailureException("Unable to retrieve array", e);
}
}
public static class MyType implements SQLData {
private String name;
private String value;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
#Override
public String getSQLTypeName() throws SQLException {
return MY_TYPE;
}
#Override
public void readSQL(SQLInput stream, String typeName) throws SQLException {
name = stream.readString();
value = stream.readString();
}
#Override
public void writeSQL(SQLOutput stream) throws SQLException {
stream.writeString(name);
stream.writeString(value);
}
#Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}
}
}
I looked at the internet and it was very difficult to get it working with the solution many people have provided.. here is working code example.. in pom.xml create this dependency.
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-oracle</artifactId>
<version>2.0.0.M1</version>
</dependency>
oracle sample code
create table employee (EMPNO number(12) not null, FNAME varchar2(60), LNAME varchar2(60), EMAIL varchar2(120));
CREATE SEQUENCE empno_seq START WITH 1 INCREMENT BY 1 NOCACHE NOCYCLE;
CREATE OR REPLACE TYPE employee_type
AS OBJECT (EMPNO number(12), FNAME varchar2(60), LNAME varchar2(60), EMAIL varchar2(120));
/
CREATE OR REPLACE TYPE employee_table_type AS TABLE OF employee_type;
/
create or replace PROCEDURE SAVE_EMPLOYEES(p_emp_insert_array in employee_table_type) AS
BEGIN
FORALL i IN p_emp_insert_array.first .. p_emp_insert_array.last
insert into employee(
empno,
FNAME,
LNAME,
EMAIL)
values (
empno_seq.nextval,
p_emp_insert_array(i).FNAME,
p_emp_insert_array(i).LNAME,
p_emp_insert_array(i).EMAIL
);
END SAVE_EMPLOYEES;
/
import com.abc.employeepoc.domain.Employee;
import org.springframework.data.jdbc.support.oracle.StructMapper;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Struct;
/**
*
* #author rsharma
*/
public class EmployeeStructMapper implements StructMapper<Employee> {
#Override
public Struct toStruct(Employee emp, Connection conn, String oracleTypeName) throws SQLException {
Object[] attributes = {
emp.getEmpno(),
emp.getFirstName(),
emp.getLastName(),
emp.getEmailAddress()
};
return conn.createStruct(oracleTypeName, attributes);
}
#Override
public Employee fromStruct(Struct struct) throws SQLException {
Employee emp= new Employee();
Object[] attributes = struct.getAttributes();
emp.setEmpno(((Number) attributes[0]).longValue());
emp.setFirstName(String.valueOf(attributes[1]));
emp.setLastName(String.valueOf(attributes[2]));
emp.setEmailAddress(String.valueOf(attributes[3]));
return emp;
}
}
SqlStructArrayValue in spring has some issue with OracleConnection casting so i created my own one similar to them.
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Struct;
import oracle.jdbc.OracleConnection;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.jdbc.support.oracle.SqlStructArrayValue;
import org.springframework.data.jdbc.support.oracle.StructMapper;
/**
*
* #author rsharma
*/
public class OracleSqlStructArrayValue<T> extends SqlStructArrayValue<T> {
private T[] values;
/**
* The object that will do the mapping *
*/
private StructMapper<T> mapper;
/**
* The type name of the STRUCT *
*/
private String structTypeName;
/**
* The type name of the ARRAY *
*/
private String arrayTypeName;
public OracleSqlStructArrayValue(T[] values, StructMapper<T> mapper, String structTypeName) {
super(values, mapper, structTypeName);
this.values = values;
this.mapper = mapper;
this.structTypeName = structTypeName;
}
public OracleSqlStructArrayValue(T[] values, StructMapper<T> mapper, String structTypeName, String arrayTypeName) {
super(values, mapper, structTypeName, arrayTypeName);
this.values = values;
this.mapper = mapper;
this.structTypeName = structTypeName;
this.arrayTypeName = arrayTypeName;
}
#Override
protected Object createTypeValue(Connection conn, int sqlType, String typeName) throws SQLException {
if (typeName == null && arrayTypeName == null) {
throw new InvalidDataAccessApiUsageException(
"The typeName for the array is null in this context. Consider setting the arrayTypeName.");
}
Struct[] structValues = new Struct[values.length];
for (int i = 0; i < values.length; i++) {
structValues[i] = mapper.toStruct(values[i], conn, structTypeName);
}
OracleConnection oracleConn = (OracleConnection) conn;
return oracleConn.createOracleArray(typeName != null ? typeName : arrayTypeName, structValues);
}
}
Now in your DAO Class do the following...
public class EmployeeDAO {
private static final Logger logger = LoggerFactory.getLogger(EmployeeDAO.class);
#Autowired
private DataSource dataSource;
private JdbcTemplate jdbcTemplate;
private SimpleJdbcCall saveEmployeesArrayCall;
#PostConstruct
private void postConstruct() {
jdbcTemplate = new JdbcTemplate(dataSource);
this.saveEmployeesArrayCall =
new SimpleJdbcCall(dataSource).withProcedureName(SQLConstants.SAVE_EMPLOYEES_STORE_PROC)
.withoutProcedureColumnMetaDataAccess()
.declareParameters(new SqlParameter("p_emp_insert_array", Types.ARRAY, SQLConstants.EMPLOYEE_OBJ_TABLE_TYPE));
}
public void saveEmployees(List<Employee> employees) {
Map<String, Object> in = new HashMap<>();
in.put("p_emp_insert_array", new OracleSqlStructArrayValue<>(employees.toArray(new Employee[0]), new EmployeeStructMapper(), SQLConstants.EMPLOYEE_OBJ_TYPE));
saveEmployeesArrayCall.execute(in);
}
}
import io.swagger.annotations.ApiModelProperty;
import java.util.Objects;
import org.springframework.data.annotation.Id;
/**
*
* #author rsharma
*/
public class Employee implements java.io.Serializable{
#Id
#ApiModelProperty(notes = "The database generated Employee Number")
private Long empno;
#ApiModelProperty(notes = "First Name of the Employee", required = true)
private String firstName;
#ApiModelProperty(notes = "Last Name of the Employee")
private String lastName;
private String emailAddress;
public Employee() {
super();
}
public Employee(Long empno, String emailAddress, String firstName, String lastName) {
this.empno = empno;
this.emailAddress = emailAddress;
this.firstName = firstName;
this.lastName = lastName;
}
public Long getEmpno() {
return empno;
}
public void setEmpno(Long empno) {
this.empno = empno;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmailAddress() {
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
#Override
public String toString() {
return "Employee{" + "empno=" + empno + ", firstName=" + firstName + ", lastName=" + lastName + ", emailAddress=" + emailAddress + '}';
}
#Override
public int hashCode() {
int hash = 7;
hash = 59 * hash + Objects.hashCode(this.empno);
return hash;
}
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Employee other = (Employee) obj;
if (!Objects.equals(this.empno, other.empno)) {
return false;
}
return true;
}
}

i am getting an error while inserting data in database by creating Class File in Asp.Net for Database Manipulations

error :: The parameterized query '(#CustomerName
varchar(50),#CustomerGender varchar(50),#Customer' expects the
parameter '#CustomerName', which was not supplied. Statement(s) could
not be prepared.
my code of .cs file is:
public class CustomerCls
{
private int custid;
public int CustomerId
{
set { custid = value; }
get { return custid; }
}
private string custname;
public string CustomerName
{
set { custname = value; }
get { return custname; }
}
private string gender;
public string CustomerGender
{
set { gender = value; }
get { return gender; }
}
private string city;
public string CustomerCity
{
set { city = value; }
get { return city; }
}
private string strcon;
public CustomerCls()
{
strcon = ConfigurationManager.ConnectionStrings["dbcon"].ConnectionString;
}
public void InsertCustomer()
{
string sql = "Insert Into Customer(Cust_Name,Cust_Gender,Cust_City) " + " VALUES(#CustomerName,#CustomerGender,#CustomerCity)";
SqlConnection con = new SqlConnection(strcon);
con.Open();
SqlCommand cmd = new SqlCommand(sql, con);
cmd.Parameters.Add("#CustomerName", SqlDbType.VarChar,50).Value = CustomerName;
cmd.Parameters.Add("#CustomerGender", SqlDbType.VarChar,50).Value = CustomerGender;
cmd.Parameters.Add("#CustomerCity", SqlDbType.VarChar,50).Value = CustomerCity;
cmd.Prepare();
cmd.ExecuteNonQuery();
con.Close();
}
}
Make sure the CustomerCls object calling the InsertCustomer() method has the necessary properties set in code before the call to the method is made:
CustomerCls oCustomerCls = new CustomerCls();
oCustomerCls.CustomerName = "John Doe";
// etc...
oCustomerCls.InsertCustomer();
Try changing these lines to
cmd.Parameters.Add("#CustomerName", SqlDbType.VarChar,50).Value = CustomerName;
cmd.Parameters.Add("#CustomerGender", SqlDbType.VarChar,50).Value = CustomerGender;
cmd.Parameters.Add("#CustomerCity", SqlDbType.VarChar,50).Value = CustomerCity;
to
cmd.Parameters.Add("#CustomerName", SqlDbType.VarChar,50).Value = custname;
cmd.Parameters.Add("#CustomerGender", SqlDbType.VarChar,50).Value = gender;
cmd.Parameters.Add("#CustomerCity", SqlDbType.VarChar,50).Value = city;

android using class annotation,getting anotation from child,decleare anotation in parent

i have some classes that they are using annotation to fetch data from db.
for example my test table is like:
public
#Table(name="test",isNamesLikeDB=true)
#Communicator(getMySelf="gettest",getOurSelf="gettestList",sendMySelf="updatetest",sendOurSelf="updatetestList")
class test_ extends Model{
public
#ID
#Expose
#SerializedName("Gid")
#Column(name="Gid")
String Gid;
public
#Expose
#SerializedName("Fname")
#Column(name="Fname")
String Fname;
public
#Expose
#SerializedName("LocalID")
#Column(name="LocalID")
int LocalID = -1;
}
Table annotation:
#Target(java.lang.annotation.ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
public #interface Table {
public String name();
public boolean isNamesLikeDB();
}
and my model class:
public abstract class Model {
boolean loadResult = false;
private boolean HasID = false;
private boolean HasValue = false;
private Manager manager=new Manager();
public boolean load() {
loadResult = false;
Table table = getClass().getAnnotation(Table.class);
if (table != null) {
String whereStatment = "";
Field fields[] = getClass().getDeclaredFields();
boolean morethan1Id = false;
for (Field field : fields) {
Column col = field.getAnnotation(Column.class);
ID fid = field.getAnnotation(ID.class);
boolean findId = false;
String column = "";
if (col != null) {
column = col.name();
}
if (fid != null) {
findId = true;
}
if (findId) {
if (morethan1Id)
whereStatment += " and " + column + "="
+ getfieldString(field,this) + " ";
else
whereStatment += "where " + column + "="
+ getfieldString(field,this) + " ";
morethan1Id = true;
}
}
Cursor c = DataSourceTools.findAllObject("select * from "
+ table.name() + " " + whereStatment);
if (c!=null&&c.moveToFirst())
loadResult = filFromCursor(c, this);
else
loadResult = false;
setHasID(loadResult);
setHasValue(loadResult);
return loadResult;
}
throw new NullPointerException(
"you must declear table annotation for your class");
}
}
public class test1 extends test_{
}
when i create another class like test1 that it extends test class i want Table annotation be accessible in test1,and no more define Table annotation for class test1 when i use this code:
new test1().load();
when i call load() method it runs load method in model class,and in model class the first thing is getting Table Annotation.
getClass().getAnnotation(Table.class);
this line returns null,but i declare table annotation for test,anyone can help me?(sorry for my bad English)
I solved it with this code:
getClass().getSuperClass().getAnnotation(Table.class);

Resources