I am using Mockito to mock queryForObject but I get NPE. Looks like I am setting everything needed.
long identity = getJdbcTemplate().queryForObject( getStatementConfiguration().getStatement( KeyConstants.CLIENT_USER_VENDOR_IDENTITY), Long.class); is where I get NPE.
MUT
public IClientUserVendorDto insert(final IClientUserVendorDto dto) throws DaoException {
try {
String sql1 = getStatementConfiguration().getStatement(KeyConstants.CLIENT_USER_VENDOR_RETRIEVE);
Object args[] = new Object[] {
dto.getClientUserId(),
dto.getVendor().getId(),
dto.getIdentifier(),
Boolean.TRUE,
dto.getCreatedBy(),
dto.getLastModifiedBy()};
//insert
String sql = getStatementConfiguration().getStatement(KeyConstants.CLIENT_USER_VENDOR_INSERT);
getJdbcTemplate().update(sql, args);
//Retrieve
long identity = getJdbcTemplate().queryForObject( getStatementConfiguration().getStatement( KeyConstants.CLIENT_USER_VENDOR_IDENTITY), Long.class);
return (ClientUserVendorDto) getJdbcTemplate().queryForObject(sql1, new Object[] {identity}, new ClientUserVendorRowMapper());
} catch (Exception e) {
String message = "An exception occurred inserting a Client User Vendor.";
IExceptionHandlerResponse r = getExceptionHandler().handleData(e, DaoException.class, message);
if (r.isRethrow()) {
DaoException daoe = (DaoException) r.getThrowable();
throw daoe;
}
throw (DaoException)r.getThrowable();
} finally {
}
}
Junit
public void testInsert() throws Exception {
AppContext.setApplicationContext(applicationContext);
IVendorDto v = new VendorDto();
IClientUserVendorDto userDto = new ClientUserVendorDto();
userDto.setActive(true);
userDto.setClientUserId(new Long(1220));
userDto.setIdentifier("JUnit-ID");
userDto.setVendor(v);
v.setId(new Long(123));
userDto.setCreatedBy("SYSTEM");
userDto.setLastModifiedBy("Junit");
ClientUserVendorDao dao = new ClientUserVendorDao();
dao.setConfiguration(daoConfiguration);
dao.setJdbcTemplate(jdbcTemplate);
BaseJdbcDao baseDao = Mockito.mock(BaseJdbcDao.class);
BaseDao baseDao2 = Mockito.mock(BaseDao.class);
IStatementConfiguration stmtConfiguration = Mockito.mock(IStatementConfiguration.class);
Mockito.when(baseDao.getJdbcTemplate()).thenReturn(jdbcTemplate);
IDaoConfiguration configuration = new DaoConfiguration();
configuration.setStatement(stmtConfiguration);
dao.setConfiguration(configuration);
Mockito.when(baseDao.getJdbcTemplate().queryForObject( Mockito.any(String.class), (RowMapper<Long>) Mockito.any(Object.class))).thenReturn(123L);
userDto = dao.insert(userDto);
}
I found out what was the issue. queryForObject was not returning a long value. So, here is the fix for it.
#Test
public void testInsert() throws Exception {
IClientUserVendorDto iClientUserVendorDto = new ClientUserVendorDto();
iClientUserVendorDto.setClientUserId(new Long(1007));
IVendorDto iVendorDto = new VendorDto();
iVendorDto.setId(new Long(1008));
iClientUserVendorDto.setVendor(iVendorDto);
iClientUserVendorDto.setIdentifier("GW_SYS_USER");
iClientUserVendorDto.setActive(true);
iClientUserVendorDto.setCreatedBy("SYSTEM");
iClientUserVendorDto.setLastModifiedBy("SYSTEM");
JdbcTemplate jdbcTemplate = Mockito.mock(JdbcTemplate.class);
ClientUserVendorDao clientUserVendroDao2 = Mockito.mock(ClientUserVendorDao.class);
IDaoConfiguration iDaoConfiguration = Mockito.mock(IDaoConfiguration.class);
IStatementConfiguration iStatementConfiguration = Mockito.mock(IStatementConfiguration.class);
Mockito.when(iDaoConfiguration.getStatement()).thenReturn(iStatementConfiguration);
Mockito.when(iStatementConfiguration.getStatement(Mockito.any(String.class))).thenReturn("JUnit");
Mockito.when(clientUserVendroDao2.getJdbcTemplate()).thenReturn(jdbcTemplate);
Mockito.when(jdbcTemplate.queryForObject(Mockito.anyString(), Matchers.eq(Long.class))).thenReturn(1007L);
ClientUserVendorDao clientUserVendorDao = new ClientUserVendorDao();
clientUserVendorDao.setConfiguration(iDaoConfiguration);
clientUserVendorDao.setJdbcTemplate(jdbcTemplate);
iClientUserVendorDto = clientUserVendorDao.insert(iClientUserVendorDto);
Related
[ISSUE] repo always returns null when I call repo methods, while stepping through, throws null pointer exception. then front end receives
500: Http failure response for http://localhost:4200/api/aiprollout/updatecsv: 500 Internal Server Error
[HAVE TRIED] Adjusting AutoWired and components and service annotations.
[QUESTIONS]
1- Does every repo method need its own service and controller method?
2- Is it okay to create a new service that uses an existing controller?
3- If this new service uses SuperCsv and I create custom CsvCellProcessors, can these cell processors also call the repo? Should these cell processors perform logic? or should it be done else where? What class annotations should these cellProcessors classes have? #Component?
Any advice is greatly appreciated, feel a little lost at this point not even sure what to do.
[CODE]
Controller:
#RestController
#EnableConfigurationProperties({SpoofingConfigurationProperties.class})
#RequestMapping(value = "")
public class AipRolloutController {
private final Logger logger = some logger
private final AipRolloutService AipRolloutService;
private final CsvParserService csvParserService;
#Autowired
public AipRolloutController(AipRolloutService aipRolloutService, CsvParserService csvParserService) {
this.AipRolloutService = aipRolloutService;
this.csvParserService = csvParserService;
}
#PostMapping(value = "/updatecsv", produces = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public ResponseEntity<?> processCsv(#RequestParam("csvFile") MultipartFile csvFile) throws IOException {
if (csvFile.isEmpty()) return new ResponseEntity(
responceJson("please select a file!"),
HttpStatus.NO_CONTENT
);
csvParserService.parseCsvFile(csvFile);
return new ResponseEntity(
responceJson("Successfully uploaded - " + csvFile.getOriginalFilename()),
new HttpHeaders(),
HttpStatus.CREATED
);
}
Service:
#Service
public class AipRolloutService {
private static final Logger logger = some logger
#Autowired
private AIPRolloutRepository AIPRolloutRepository;
New Csv parser Service
#Service
public class CsvParserService {
#Autowired private AipRolloutService aipRolloutService;
public CsvParserService(AipRolloutService aipRolloutService) {
this.aipRolloutService = aipRolloutService;
}
public void parseCsvFile(MultipartFile csvFile) throws IOException {
CsvMapReader csvMapReader = new CsvMapReader(new InputStreamReader(csvFile.getInputStream()), CsvPreference.STANDARD_PREFERENCE);
parseCsv(csvMapReader);
csvMapReader.close();
}
private void parseCsv(CsvMapReader csvMapReader) throws IOException {
String[] header = csvMapReader.getHeader(true);
List<String> headers = Arrays.asList(header);
verifySourceColumn(headers);
verifyPovColumn(headers);
final CellProcessor[] processors = getProcessors(headers);
Map<String, Object> csvImportMap = null;
while ((csvImportMap = csvMapReader.read(header, processors)) != null) {
CsvImportDTO csvImportDto = new CsvImportDTO(csvImportMap);
if ( activationTypeP(csvImportDto) ){
int mssValue = Integer.parseInt(csvImportDto.getMssValue());
aipRolloutService.updateAipRollout(csvImportDto.getSource(),
csvImportDto.getPov(),
csvImportDto.getActivationType(),
mssValue);
}
}
}
private CellProcessor[] getProcessors(List<String> headers) {
CellProcessor[] processors = new CellProcessor[headers.size()];
int index = 0;
for (String header : headers) {
if (header.contains(SOURCE_ID)) {
processors[index++] = new CsvSourceIdCellParser();
} else if (header.contains(POV)) {
processors[index++] = new CsvPovCellParser();
} else if (header.contains(ACTIVATION_TYPE)) {
processors[index++] = new CsvActivationTypeCellParser();
} else if (header.contains(ACTIVATION_DATE)) {
processors[index++] = new Optional();
} else if (header.contains(DEACTIVATION_DATE)) {
processors[index++] = new Optional();
} else if (header.contains(MSS_VALUE)) {
processors[index++] = new CsvMssValueCellParser();
} else {
processors[index++] = null; // throw exception? wrong header info instead of allowing null?
}
}
return processors;
}
Custom Cell Processor that calls repo and returns null
public class CsvSourceIdCellParser extends CellProcessorAdaptor {
#Autowired AIPRolloutRepository aipRolloutRepository;
public CsvSourceIdCellParser(){ super(); }
// this constructor allows other processors to be chained
public CsvSourceIdCellParser(CellProcessor next){ super(next); }
#Override
public Object execute(Object value, CsvContext csvContext) {
// throws an Exception if the input is null
validateInputNotNull(value, csvContext);
// get rid of description only need first 3 #'s
value = value.toString().substring(0,3);
// check if WH exists
if( aipRolloutRepository.dcExistsInDatabase(value.toString()) )
return value;
else
throw new RuntimeException("Check Warehouse Value, Value Not Found "
+ "Row number: " + csvContext.getRowNumber()
+ " Column number: " + csvContext.getColumnNumber());
}
}
Repository
#Repository
public class AIPRolloutRepository {
private static final Logger logger = LoggerFactory.getLogger(AIPRolloutRepository.class);
#Autowired
JdbcTemplate jdbcTemplate;
public AIPRolloutRepository() {
}
public boolean dcExistsInDatabase(String dc){
// Query for a count saves time and memory, query for distinct saves time and memory on execution
boolean hasRecord =
jdbcTemplate
.query( "select count (distinct '" + dc +"')" +
"from xxcus.XX_AIP_ROLLOUT" +
"where DC = '" + dc + "';",
new Object[] { dc },
(ResultSet rs) -> {
if (rs.next()) {
return true;
}
return false;
}
);
return hasRecord;
}
I'am creating a restapi , i am using java spring and i'am getting the following error.
Error:
org.springframework.dao.EmptyResultDataAccessException: Incorrect result size: expected 1, actual 0
My daoImpl class
#Override
public String getLoginDetails(VendorLogin vendorlogin) {
String getVendorData = "select vendor_ID from vendor_login where vendor_ID= ?
and password=?";
String name =null;
try{
name = (String) jdbcTemplate.queryForObject(getVendorData,new Object[]{
vendorlogin.getVendorLoginId(), vendorlogin.getPassWord()}, String.class);
}catch(Exception e){
e.printStackTrace();
}
return name;
}
my controller
#RequestMapping(value = Constants.REQ_MAP_LOGIN,
method = RequestMethod.POST,
produces = MediaType.APPLICATION_JSON_VALUE)
public String vendorloginMethodPost(#RequestBody VendorLogin vendoridlogin) {
String message = Constants.EMPTY_STRING;
String id = dao.getLoginDetails(vendoridlogin);
String password = dao.getLoginDetails(vendoridlogin);
if (id == null && password==null) {
message = "login FAIL";
}else{
message =" login Successfully";
}
return message;
}
SOLUTION
#Override
public String getLoginDetails(VendorLogin vendorlogin) {
String getVendorData = "select vendor_ID from vendor_login where vendor_ID= ? and password=?";
try {
name = (String) jdbcTemplate.queryForObject(
getVendorData,
new Object[]{vendorlogin.getVendorLoginId(), vendorlogin.getPassWord()},
new RowMapper<YourVendorObject>() {
public UserAttempts mapRow(ResultSet rs, int rowNum) throws SQLException {
// we suppose that your vendor_ID is String in DB
String vendor_ID = rs.getString("vendor_ID");
// if you wanna return the whole object use setters and getters
// from rs.getInt ... rs.getString ...
return vendor_ID;
}
});
return name;
} catch (EmptyResultDataAccessException e) {
return null;
}
}
public class EmptyResultDataAccessException extends IncorrectResultSizeDataAccessException
Data access exception thrown when a result was expected to have at least one row (or element) but zero rows (or elements) were actually returned.
The problem is, Spring throws an EmptyResultDataAccessException, instead of returning a null when record not found :
JdbcTemplate .java
package org.springframework.jdbc.core;
public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
//...
public <T> T queryForObject(String sql, Object[] args,
RowMapper<T> rowMapper) throws DataAccessException {
List<T> results = query(sql, args, new RowMapperResultSetExtractor<T>(rowMapper, 1));
return DataAccessUtils.requiredSingleResult(results);
}
DataAccessUtils.java
package org.springframework.dao.support;
public abstract class DataAccessUtils {
//...
public static <T> T requiredSingleResult(Collection<T> results)
throws IncorrectResultSizeDataAccessException {
int size = (results != null ? results.size() : 0);
if (size == 0) {
throw new EmptyResultDataAccessException(1);
}
if (results.size() > 1) {
throw new IncorrectResultSizeDataAccessException(1, size);
}
return results.iterator().next();
}
check it here : source
try {
String getVendorData = "select vendor_ID from vendor_login where vendor_ID= ? and password=?";
String name =null;
name = (String) jdbcTemplate.queryForObject(getVendorData,new Object[]{vendorlogin.getVendorLoginId(), vendorlogin.getPassWord()}, String.class);
} catch (EmptyResultDataAccessException e) {
return null;
}
Mocked jdbcTemplate doesn't return the desired List. ( Another stub works correctly with a basic Integer type.) I tried both with thenReturn and thenAnswer but it didn't helped. Neither thenReturn nor thenAnswer worked.
I have to stub these 2 jdbcTemplate queries: (
...
List<V_MONITORING_Record> vMonitoring_Record_List = new ArrayList<>();
...
try {
vMonitoring_Record_List = jdbcTemplate.query(SELECT_V_MONITORING,
namedParameters,
new BeanPropertyRowMapper<>(V_MONITORING_Record.class));
} catch (DataAccessException exception) {
}
try {
Integer count = jdbcTemplate.queryForObject(SELECT_MONTHLYTABLES.toString(), namedParameters, Integer.class);}
catch(...){}
#RunWith(MockitoJUnitRunner.class)
public class MonitoringTest {
#MockBean
NamedParameterJdbcTemplate jdbcTemplate = Mockito.mock(NamedParameterJdbcTemplate.class);
#InjectMocks
private MonitoringProcessorNode MonitoringProcessorNode;
#Mock
private EmailServiceImpl emailServiceImpl;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
#Test
public void test1(){
Answer<List<V_MONITORING_Record>> ans_V_MONITORING = inv -> {
List<V_MONITORING_Record> vMonitoring_Record_List = new ArrayList<>();
V_MONITORING_Record rec = new V_MONITORING_Record();
rec.setANZAHL(123);
...
vMonitoring_Record_List.add(rec);
return vMonitoring_Record_List;
};
Answer<Integer> ans_Integer = new Answer<Integer>(){
#Override
public Integer answer( InvocationOnMock inv)throws Throwable{
return 3;
}
};
MapSqlParameterSource namedParameters = new MapSqlParameterSource();
//This doesn't work
Mockito.when(jdbcTemplate.query("select * from V_MONITORING", namedParameters, new BeanPropertyRowMapper<>(V_MONITORING_ELINK_Record.class))).thenAnswer(ans_V_MONITORING);
//This works correctly
Mockito.when(jdbcTemplate.queryForObject(eq("select count(*) from TEST_TABLE_1"), (MapSqlParameterSource)any(), eq(Integer.class))).thenAnswer(ans_Integer);
}
I need to write a unit test for solr SearchComponent (SearchComponent.process ()).
How could I do that? Can I use SolrTestCaseJ4 or another way?
I am currently using SolrTestCaseJ4...
I am currently using SolrTestCaseJ4...
public class SearchComponentTest extends SolrTestCaseJ4 {
#BeforeClass
public static void beforeClass() throws Exception {
initCore("collection1/conf/solrconfig.xml", "collection1/conf/schema.xml", "src/test/resources/");
}
#Test
public void testPrepare() throws IOException {
MySearchComponent component = new MySearchComponent();
List<SearchComponent> components = new ArrayList<>();
components.add(component);
SolrQueryRequest req;
ResponseBuilder rb;
req = req("q", "*:*");
rb = new ResponseBuilder(req, new SolrQueryResponse(), components);
component.process(rb);
}
}
and my SearchComponent:
public class MySearchComponent extends SearchComponent {
public void process(ResponseBuilder rb) throws IOException {
....
SolrQueryRequest req = rb.req;
SolrQueryResponse rsp = rb.rsp;
SolrParams params = rb.req.getParams();
SchemaField keyField = rb.req.getCore().getLatestSchema().getUniqueKeyField();
String core = rb.req.getCore().getName();
SolrIndexSearcher searcher = req.getSearcher();
QueryCommand cmd = rb.createQueryCommand();
QueryResult result = new QueryResult();
searcher.search(result, cmd);
rb.setResult(result);
BasicResultContext ctx = new BasicResultContext(rb, rb.getResults().docList);
rsp.add("response", ctx);
...
}
...
}
But i have NullPointerException on this line:
QueryCommand cmd = rb.createQueryCommand();
Thank you for your help!
I use mybatis to perform sql queries in my project. I need to intercept sql query before executing to apply some changed dynamically. I've read about #Interseptors like this:
#Intercepts({#Signature(type= Executor.class, method = "query", args = {...})})
public class ExamplePlugin implements Interceptor {
public Object intercept(Invocation invocation) throws Throwable {
return invocation.proceed();
}
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
public void setProperties(Properties properties) {
}
}
And it really intercepts executions, but there is no way to change sql query since appropriate field is not writable. Should I build new instance of whole object manually to just replace sql query? Where is the right place to intercept query execution to change it dynamically? Thank.
I hope it will help you:
#Intercepts( { #Signature(type = Executor.class, method = "query", args = {
MappedStatement.class, Object.class, RowBounds.class,
ResultHandler.class
})
})
public class SelectCountSqlInterceptor2 implements Interceptor
{
public static String COUNT = "_count";
private static int MAPPED_STATEMENT_INDEX = 0;
private static int PARAMETER_INDEX = 1;
#Override
public Object intercept(Invocation invocation) throws Throwable
{
processCountSql(invocation.getArgs());
return invocation.proceed();
}
#SuppressWarnings("rawtypes")
private void processCountSql(final Object[] queryArgs)
{
if (queryArgs[PARAMETER_INDEX] instanceof Map)
{
Map parameter = (Map) queryArgs[PARAMETER_INDEX];
if (parameter.containsKey(COUNT))
{
MappedStatement ms = (MappedStatement) queryArgs[MAPPED_STATEMENT_INDEX];
BoundSql boundSql = ms.getBoundSql(parameter);
String sql = ms.getBoundSql(parameter).getSql().trim();
BoundSql newBoundSql = new BoundSql(ms.getConfiguration(),
getCountSQL(sql), boundSql.getParameterMappings(),
boundSql.getParameterObject());
MappedStatement newMs = copyFromMappedStatement(ms,
new OffsetLimitInterceptor.BoundSqlSqlSource(newBoundSql));
queryArgs[MAPPED_STATEMENT_INDEX] = newMs;
}
}
}
// see: MapperBuilderAssistant
#SuppressWarnings({ "unchecked", "rawtypes" })
private MappedStatement copyFromMappedStatement(MappedStatement ms,
SqlSource newSqlSource)
{
Builder builder = new MappedStatement.Builder(ms.getConfiguration(), ms
.getId(), newSqlSource, ms.getSqlCommandType());
builder.resource(ms.getResource());
builder.fetchSize(ms.getFetchSize());
builder.statementType(ms.getStatementType());
builder.keyGenerator(ms.getKeyGenerator());
// setStatementTimeout()
builder.timeout(ms.getTimeout());
// setParameterMap()
builder.parameterMap(ms.getParameterMap());
// setStatementResultMap()
List<ResultMap> resultMaps = new ArrayList<ResultMap>();
String id = "-inline";
if (ms.getResultMaps() != null)
{
id = ms.getResultMaps().get(0).getId() + "-inline";
}
ResultMap resultMap = new ResultMap.Builder(null, id, Long.class,
new ArrayList()).build();
resultMaps.add(resultMap);
builder.resultMaps(resultMaps);
builder.resultSetType(ms.getResultSetType());
// setStatementCache()
builder.cache(ms.getCache());
builder.flushCacheRequired(ms.isFlushCacheRequired());
builder.useCache(ms.isUseCache());
return builder.build();
}
private String getCountSQL(String sql)
{
String lowerCaseSQL = sql.toLowerCase().replace("\n", " ").replace("\t", " ");
int index = lowerCaseSQL.indexOf(" order ");
if (index != -1)
{
sql = sql.substring(0, index);
}
return "SELECT COUNT(*) from ( select 1 as col_c " + sql.substring(lowerCaseSQL.indexOf(" from ")) + " ) cnt";
}
#Override
public Object plugin(Object target)
{
return Plugin.wrap(target, this);
}
#Override
public void setProperties(Properties properties)
{
}
}
You may consider using a string template library (eg Velocity, Handlebars, Mustache) to help you
As of to date, there is even MyBatis-Velocity (http://mybatis.github.io/velocity-scripting/) to help you to do scripting for the sql.
Depending on the changes you want to make, you may want to use the dynamic sql feature of mybatis 3