MockMVC not mapping query parameters - testing

When I test REST API endpoints using POSTMAN, It works fine. This is the console message.
path : -1
****** doFilter!!!!!!!!!!!!!!!!!!!
2018-11-15 10:52:56,949 DEBUG [com.isu.ifm.wrapper.RequestWrapper::<init>:85] URI : /ifm/Board.do
2018-11-15 10:52:56,949 DEBUG [com.isu.ifm.wrapper.RequestWrapper::<init>:86] METHOD : GET
2018-11-15 10:52:56,950 DEBUG [com.isu.ifm.wrapper.RequestWrapper::<init>:126] PARAM : comments : [a]
enterCd : [ISU_PS]
bbsCd : [10003]
bbsSeq : [1]
cmd : [saveCmt]
sabun : [91006]
preHandler ::::::::::::::http://localhost:8083/ifm/Board.do
ISU_PS
91006
preHandler ::::::::::::::/ifm/Board.do
[2018-11-15 10:52:56] [DEBUG]『org.apache.commons.dbcp.PoolingDataSource:getConnection(106)』 Elapsed Time [0:00:00.007]
select
1
from
dual
[2018-11-15 10:52:56] [DEBUG]『org.springframework.jdbc.core.JdbcTemplate:execute(644)』 Elapsed Time [0:00:00.023]
INSERT INTO TSYS730(ENTER_CD, SABUN, BBS_SEQ, COMMENTS_SEQ, COMMENTS, CHKDATE, CHKID, BBS_CD)
VALUES( 'ISU_PS' /**PARAM*/, '91006' /**PARAM*/, '1' /**PARAM*/, BOARD_COMTSEQ.nextval, 'a' /**PARAM*/, sysdate, '91006' /**PARAM*/, '10003' /**PARAM*/)
Query Result[INSERT]: 1row
2018-11-15 10:52:56,984 DEBUG [com.isu.ifm.wrapper.ResponseWrapper::toByteArray:95] RETURN VALUE : {"message":"","map":{"comments":"a","enterCd":"ISU_PS","bbsCd":"10003","bbsSeq":"1","cmd":"saveCmt","sabun":"91006","ssnEnterCd":"ISU_PS","ssnSabun":"91006"},"code":1}
But when I try to test same endpoints using jUnit with MockMVC, it gets parameters but cannot map in query.
ERROR [org.anyframe.query.QueryService::processException:1889] Query Service : Fail to [update [query id = 'saveCmt'],
INSERT INTO TSYS730(ENTER_CD, SABUN, BBS_SEQ, COMMENTS_SEQ, COMMENTS, CHKDATE, CHKID, BBS_CD)
VALUES(:ssnEnterCd, :ssnSabun, :bbsSeq, BOARD_COMTSEQ.nextval, :comments, sysdate, :ssnSabun, :bbsCd)
, PreparedStatementCallback; SQL [
INSERT INTO TSYS730(ENTER_CD, SABUN, BBS_SEQ, COMMENTS_SEQ, COMMENTS, CHKDATE, CHKID, BBS_CD)
VALUES(?, ?, ?, BOARD_COMTSEQ.nextval, ?, sysdate, ?, ?)
]; ORA-01400: cannot insert NULL in ("EHR_ISU4"."TSYS730"."ENTER_CD")
; nested exception is java.sql.SQLIntegrityConstraintViolationException: ORA-01400: cannot insert NULL in ("EHR_ISU4"."TSYS730"."ENTER_CD")
].
Query = [org.springframework.dao.DataIntegrityViolationException: PreparedStatementCallback; SQL [
INSERT INTO TSYS730(ENTER_CD, SABUN, BBS_SEQ, COMMENTS_SEQ, COMMENTS, CHKDATE, CHKID, BBS_CD)
VALUES(?, ?, ?, BOARD_COMTSEQ.nextval, ?, sysdate, ?, ?)
]; ORA-01400: cannot insert NULL in ("EHR_ISU4"."TSYS730"."ENTER_CD")
; nested exception is java.sql.SQLIntegrityConstraintViolationException: ORA-01400: cannot insert NULL in ("EHR_ISU4"."TSYS730"."ENTER_CD")
]
Reason = [{}].
MockHttpServletRequest:
HTTP Method = GET
Request URI = /Board.do
Parameters = {cmd=[saveCmt], enterCd=[ISU_PS], sabun=[91006], bbsCd=[10001], bbsSeq=[1], comments=[a]}
Headers = {}
Handler:
Type = com.isu.ifm.controller.BoardController
Method = public org.springframework.web.servlet.ModelAndView com.isu.ifm.controller.BoardController.saveCmt(javax.servlet.http.HttpSession,javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.Object>) throws java.lang.Exception
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = jsonView
View = null
Attribute = code
value = -1
Attribute = message
value = fail
Attribute = map
value = {cmd=saveCmt, enterCd=ISU_PS, sabun=91006, bbsCd=10001, bbsSeq=1, comments=a, ssnEnterCd=null, ssnSabun=null}
FlashMap:
MockHttpServletResponse:
Status = 200
Error message = null
Headers = {}
Content type = null
Body =
Forwarded URL = jsonView
Redirected URL = null
Cookies = []
2018-11-15 10:49:19,788 INFO [org.springframework.context.support.GenericApplicationContext::doClose:862] Closing org.springframework.context.support.GenericApplicationContext#9660f4e: startup date [Thu Nov 15 10:49:14 KST 2018]; root of context hierarchy
Here is my testcase code.
public MockMvc mockMvc;
public void testGetMethod_param(String url, UnaryOperator<MockHttpServletRequestBuilder> operator)
throws Exception {
mockMvc.perform(operator.apply(get(url))).andDo(print()).andExpect(status().isOk());
}
#ContextConfiguration("file:src/main/webapp/WEB-INF/**/*.xml")
public class BoardControllerTest extends HttpRequestTestMethod implements CoreParameters, AdapterServiceParameters{
#Autowired
public BoardController boardController;
#Before
public void setUp() throws Exception {
mockMvc = MockMvcBuilders.standaloneSetup(boardController).build();
}
#Test
public void savecmt() throws Exception {
testGetMethod_param("/Board.do", builder->builder
.param("cmd", "saveCmt")
.param("enterCd", enterCd)
.param("sabun", sabun)
.param("bbsCd", bbsCd)
.param("bbsSeq", bbsSeq)
.param("comments", comments));
}
If I deliberately set enterCd to NULL, I get this following message.
[2018-11-15 11:06:02] [ERROR]『oracle.jdbc.driver.T4CTTIoer:processError(439)』
java.sql.SQLIntegrityConstraintViolationException
INSERT INTO TSYS730(ENTER_CD, SABUN, BBS_SEQ, COMMENTS_SEQ, COMMENTS, CHKDATE, CHKID, BBS_CD)
VALUES( null /**PARAM*/, '91006' /**PARAM*/, '1' /**PARAM*/, BOARD_COMTSEQ.nextval, 'a' /**PARAM*/, sysdate, '91006' /**PARAM*/, '10003' /**PARAM*/)
ORA-01400: cannot insert Null in ("EHR_ISU4"."TSYS730"."ENTER_CD")
But as attached above, when using jUnit, all parameters are set to "?"
Query = [org.springframework.dao.DataIntegrityViolationException: PreparedStatementCallback; SQL [
INSERT INTO TSYS730(ENTER_CD, SABUN, BBS_SEQ, COMMENTS_SEQ, COMMENTS, CHKDATE, CHKID, BBS_CD)
VALUES(?, ?, ?, BOARD_COMTSEQ.nextval, ?, sysdate, ?, ?)
]; ORA-01400: cannot insert Null in ("EHR_ISU4"."TSYS730"."ENTER_CD")
; nested exception is java.sql.SQLIntegrityConstraintViolationException: ORA-01400: cannot insert Null in ("EHR_ISU4"."TSYS730"."ENTER_CD")
]
Can anyone tell me what is wrong here?
Any help would be greatly appreciated.

Related

MariaDB Node.js-Connector insert a value and use the default value

I have a MariaDB database in conjuction with an Express.js backend and therefore use the MariaDB provided Node.js Connector. I Initialized a Database with a Table that looks like this:
CREATE TABLE IF NOT EXISTS `Threads` (
`id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
`title` TINYTEXT NOT NULL,
`post` TEXT NOT NULL,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
`updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL,
PRIMARY KEY (`id`)
);
Using the Node.js-Connector in my Backend, I want to insert some data to this table and use the default values for "created_at" and "updated_at".
I was thinking of something like this:
const insertThreadQuery = 'INSERT INTO Threads VALUES (?, ?, ?, ?, ?)';
con = await pool.getConnection();
const result = await con.query(insertThreadQuery, [null, "title", "post", null, null]);
Which obivously throws an error that tells me, that I cannot insert null for these Values ((conn=4, no: 1048, SQLState: 23000) Column 'updated_at' cannot be null sql: INSERT INTO Threads VALUES (?, ?, ?, ?, ?) - parameters:[null,'title','post',null,null])
My question is: How can I insert an entry like I was showing before, but instead of inserting "null" insert something else so my columns created_at and updated_at use the default value?
If you want to use DEFAULT values, then pass DEFAULT instead of NULL.
const insertThreadQuery = 'INSERT INTO Threads VALUES (NULL, ?, ?, DEFAULT, DEFAULT)';
con = await pool.getConnection();
const result = await con.query(insertThreadQuery, ["title", "post"]);

DB2 multiple SQL update statements

I am not very experienced with SQL outside of the basics. I'm identifying places in our code that need refactoring and I am trying to optimize some code to limit the number of calls to the DB. I've found some SQL updates that are all updating the same table and am curious how I could go about this...
Here are the update statements:
Host Variables:
[u.contentTitle, u.contentDescription, "title and dscr update", u.urlId, u.statusCode, u.urlId, u.statusCode]
[u.contentTitle, u.contentDescription, "title and dscr update", u.urlId, u.statusCode, u.urlId, u.statusCode]
[null, null, 'title and dscr update', u.urlId, u.statusCode]
UPDATE URL
SET CONTENT_TITLE = ?,
CONTENT_DSCR = ?,
SYSTEM_UPDATE_REASON = ?,
UPDATED_ON = SYSDATE
WHERE ID = ?
AND CONTENT_TITLE IS NULL
AND ? NOT BETWEEN 400 AND 599 OR ID = ?
AND CONTENT_TITLE = ''
AND ? NOT BETWEEN 400 AND 599
UPDATE URL
SET CONTENT_TITLE = ?,
CONTENT_DSCR = ?,
SYSTEM_UPDATE_REASON = ?,
UPDATED_ON = SYSDATE
WHERE ID = ?
AND CONTENT_DSCR IS NULL
AND ? NOT BETWEEN 400 AND 599 OR ID = ?
AND CONTENT_DSCR = ''
AND ? NOT BETWEEN 400 AND 599
UPDATE URL
SET CONTENT_TITLE = ?,
CONTENT_DSCR = ?,
SYSTEM_UPDATE_REASON = ?,
UPDATED_ON = SYSDATE
WHERE ID = ?
AND CONTENT_TITLE IS NOT NULL
AND ? BETWEEN 400 AND 599
All 3 statements are called during our scraping process... so you can imagine it's triple the calls which is not something we want. Can this be done in one single update?

Why do I get syntax error for "INSERT INTO"?

String pName = getStrFromUser("Product name: ");
int price = getIntFromUser("Price: ", false);
String category = getStrFromUser("Category: ");
String description = getStrFromUser("Description: ");
PreparedStatement statement = connection.prepareStatement("INSERT INTO ws.products (name, price, cid, description) VALUES (?, ?, (SELECT ws.categories.cid FROM ws.categories WHERE ws.categories.name LIKE ?), ?)");
statement.setString(1, pName);
statement.setInt(2, price);
statement.setString(3, category);
statement.setString(4, description);
statement.executeUpdate();
I get:
Error encountered: ERROR: syntax error at or near "INSERT INTO ws
What might be the problem?
The subquery inside the VALUES clause looks suspicious. Try rephrasing as an INSERT INTO ... SELECT:
String sql = "INSERT INTO ws.products (name, price, cid, description) ";
sql += "SELECT ?, ?, cid, ? FROM ws.categories WHERE name LIKE ?";
PreparedStatement statement = connection.prepareStatement(sql);
statement.setString(1, pName);
statement.setInt(2, price);
statement.setString(3, description);
statement.setString(4, category);
statement.executeUpdate();
I would recommend insert . . . select:
INSERT INTO ws.products (name, price, cid, description)
SELECT ?, ?, ws.categories.cid, ?
FROM ws.categories
WHERE ws.categories.name LIKE ?;
This will not fix the problem with INSERT, but it will prevent the next problem of a subquery returning more than one row.
My best guess for that problem is that the library you are using only supports SELECT statements. That would be atypical; INSERT is usually allowed.

Change Spring Data Rest default message for DataIntegrityViolationException

I have a basic JPA Entity that I would like to expose via Spring-Data-Rest
#Entity
#Table(name='test')
class Test{
#Id
Long id
#Column(name='other_id', unique = true)
String otherId
#Column(name='other_crm_id')
String otherCrmId
#Column(name='created_date')
Date createdDate
#Column(name='created_by')
String createdBy
}
I would like to change the exception message that is thrown when the Unique constraint on 'otherId' fires. Currently the default ExceptionHandler for Spring Data Rest displays the following
{
-cause: {
-cause: {
cause: null
message: "Unique index or primary key violation:
\"UK_PJCWVB8DO3C89YTD1PNF85HQR_INDEX_2 ON PUBLIC.TEST(OTHER_ID) VALUES
( /* key:1 */ 2, NULL, NULL, 'ABC123424', '123')\"; SQL statement:\
insert into test (id, created_by, created_date, other_crm_id,
other_id) values (null, ?, ?, ?, ?) [23505-175]"
}
message: "could not execute statement"
}
message: "could not execute statement; SQL [n/a]; constraint
[\"UK_PJCWVB8DO3C89YTD1PNF85HQR_INDEX_2 ON PUBLIC.TEST(OTHER_ID) VALUES ( /* key:1
*/ 2, NULL, NULL, 'ABC123424', '123')\"; SQL statement:\ insert into test (id,
created_by, created_date, other_crm_id, other_id) values (null, ?, ?, ?, ?)
[23505-175]]; nested exception is
org.hibernate.exception.ConstraintViolationException: could not execute statement"
}
Not a big fan of the sql and table information being returned in the Response, so I've been attempting to change the message. I created a ExceptionHandlingController annotated with #ControlAdvice, but the ExceptionHandlers in AbstractRepositoryRestController.java take precedence.
My question is: What is the best way to change the error response for the DataIntegrityViolationException in Spring-Data-Rests default RepositoryEntityController?

SQL Hibernate error

I'm using a helper class and trying to insert some data into a db table. I have one self join class with a onetomany relationship.
The main class for the insert transaction
public static void main(String[] args) {
// TODO Auto-generated method stub
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction transaction = null;
try {
transaction = session.beginTransaction();
// Create new checker
Staff checker = new Staff();
checker.setStaffId("d8");
checker.setEmail("do#msn.com");
checker.setName("Doris");
checker.setPassword("890");
checker.setUsername("dr89");
// Create new staff
Staff staff1 = new Staff();
staff1.setStaffId("m6");
staff1.setEmail("mr#msn.com");
staff1.setName("Marius");
staff1.setPassword("234");
staff1.setUsername("mr23");
Staff staff2 = new Staff();
staff2.setStaffId("b8");
staff2.setEmail("be#msn.com");
staff2.setName("Betty");
staff1.setPassword("567");
staff1.setUsername("be56");
Set<Staff> staff = new HashSet<Staff>();
staff.add(staff1);
staff.add(staff2);
staff1.setChecker(checker);
staff2.setChecker(checker);
checker.setSetters(staff);
session.save(checker);
session.save(staff1);
session.save(staff2);
transaction.commit();
}catch (HibernateException e) {
transaction.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
the DB
CREATE TABLE `staff` (
`staff_id` VARCHAR(255) NOT NULL,
`name` VARCHAR(255) NULL DEFAULT NULL,
`username` VARCHAR(255) NOT NULL,
`password` VARCHAR(255) NOT NULL,
`email` VARCHAR(255) NULL DEFAULT NULL,
`checker_id` VARCHAR(255) NULL DEFAULT NULL,
PRIMARY KEY (`staff_id`),
FOREIGN KEY (`checker_id`) REFERENCES `staff` (`staff_id`));
After I ran the code, it came up with a constraint violation at the column password.
The query and warning in the stacktrace:
Hibernate: select staff_.staff_id, staff_.checker_id as checker6_2_, staff_.email
as email2_, staff_.name as name2_, staff_.password as password2_, staff_.username as
username2_ from staff staff_ where staff_.staff_id=?
Hibernate: select staff_.staff_id, staff_.checker_id as checker6_2_, staff_.email as
email2_, staff_.name as name2_, staff_.password as password2_, staff_.username as
username2_ from staff staff_ where staff_.staff_id=?
Hibernate: insert into staff (checker_id, email, name, password, username, staff_id)
values (?, ?, ?, ?, ?, ?)
Hibernate: insert into staff (checker_id, email, name, password, username, staff_id)
values (?, ?, ?, ?, ?, ?)
Hibernate: insert into staff (checker_id, email, name, password, username,
staff_id)
values (?, ?, ?, ?, ?, ?)
WARN : org.hibernate.engine.jdbc.spi.SqlExceptionHelper - SQL Error: 1048, SQLState:
23000
ERROR: org.hibernate.engine.jdbc.spi.SqlExceptionHelper - Column 'password' cannot
be null
The full error
org.hibernate.exception.ConstraintViolationException: Column 'password' cannot be null
at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:74)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110)
at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:129)
at org.hibernate.engine.jdbc.internal.proxy.AbstractProxyHandler.invoke(AbstractProxyHandler.java:81)
at $Proxy16.executeUpdate(Unknown Source)
at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:56)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3028)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3469)
at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:88)
at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:362)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:354)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:275)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:326)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1213)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:402)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175)
at com.project.professional.StaffRelationshipTest.main(StaffRelationshipTest.java:75)
Yes, I set the password in the table to not null, and I have added some data to put it in the main class, so it should not be null. So I'm not sure why the error.
Typo;
Staff staff2 = new Staff();
staff2.setStaffId("b8");
staff2.setEmail("be#msn.com");
staff2.setName("Betty");
staff1.setPassword("567"); << should be staff2
staff1.setUsername("be56"); << should be staff2
Since the password is never set on staff2, the insert (rightly so) fails.