Null Pointer Exception Traced to Line 90 of CommentPostgres.java, SQL works correctly in DBeaver, Test does not - amazon-rds

All code for entire project is available here
The database is PostgreSQL 12.7
The backend is Java 11.0.12
I am building my TDD tests with JUnit 5.8.1
Here is CommentDaoTest.java
None of it is working, but I am specifically working on getAllNotNull
Line one of the method gets an exception response that leads to a NullPointerException on line 90 of CommentPostgres.java
package com.revature.data;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import java.util.Set;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import com.revature.beans.Comment;
import com.revature.data.postgres.CommentPostgres;
public class CommentDaoTest {
private CommentDAO cd = new CommentPostgres();
#BeforeEach
public void setup()
{
cd = new CommentPostgres();
}
#Test
public void getByIdNotNull()
{
Comment actual = cd.getById(1);
assertNotEquals(null, actual);
}
#Test
public void getByIdValidComment()
{
String expected = "Polarised methodical access";
Comment one = cd.getById(1);
String actual = one.getCommentText();
assertEquals(expected, actual);
}
#Test
public void getAllNotNull()
{
Set<Comment> actual = cd.getAll();
assertNotEquals(null, actual);
}
}
Here is the relevant part of CommentPostgres.java...
#Override
public Set<Comment> getAll() {
Set<Comment> comments = new HashSet<>();
try (Connection conn = connUtil.getConnection()) {
String sql = "select * from comment";
Statement stmt = conn.createStatement();
ResultSet resultSet = stmt.executeQuery(sql);
while (resultSet.next()) {
Comment comment = new Comment();
comment.setCommentId(resultSet.getInt("comment_id"));
comment.setCommentText(resultSet.getString("comment_text"));
**Line 90** comment.getApprover().setEmpId(resultSet.getInt("approver_id"));
comment.getRequest().setReqId(resultSet.getInt("req_id"));
comment.setSentAt(resultSet.getTimestamp("sent_at").toLocalDateTime());
System.out.println(comment);
comments.add(comment);
}
} catch (SQLException e) {
e.printStackTrace();
}
return comments;
}
Here is the relevant SQL
create table if not exists employee (
emp_id serial unique primary key,
first_name varchar(40),
last_name varchar(40),
username varchar(30),
passwd varchar(25),
role_id integer not null references user_role,
funds real,
supervisor_id integer,
dept_id integer
);
create table if not exists reimbursement (
req_id serial unique primary key,
emp_id integer references employee,
event_date date,
event_time time,
location varchar(50),
description varchar(75),
cost real,
grading_format_id integer references grading_format,
event_type_id integer references event_type,
status_id integer references status,
submitted_at time
);
create table if not exists comment (
comment_id serial unique primary key,
req_id integer references reimbursement,
approver_id integer references employee,
comment_text varchar(100),
sent_at time
);
INSERT INTO comment
(req_id, approver_id, comment_text, sent_at)
VALUES
(1, 43, 'Polarised methodical access', '8:56:03'),
(2, 34, 'Decentralized 3rd generation encryption', '16:26:13'),
(3, 1, 'Open-architected asymmetric firmware', '3:52:08'),
(4, 34, 'Upgradable content-based synergy', '8:01:03'),
(6, 49, 'Progressive foreground frame', '7:35:55'),
(7, 43, 'Persevering didactic definition', '16:55:07'),
(8, 43, 'Proactive responsive success', '2:21:47'),
(9, 17, 'Devolved content-based task-force', '22:04:18'),
(10, 43, 'Self-enabling client-server orchestration', '9:03:46'),
(13, 49, 'Pre-emptive stable encoding', '12:47:36'),
(14, 11, 'Streamlined asymmetric initiative', '17:45:58'),
(15, 43, 'Open-architected web-enabled leverage', '2:19:17'),
(17, 43, 'Innovative transitional alliance', '12:43:29'),
(19, 1, 'Organized didactic protocol', '3:54:43'),
(20, 17, 'Switchable 5th generation solution', '20:54:12');
The scripts holding the rest of it are on github in the link at the top.
When I do a
SELECT * FROM comment;
in DBeaver I get all of the comments with approver_id's
however when I run getAllNotNull I get a NullPointer pointing at the approver_id. I put a Sys.out trying to catch to comment a few lines below 90, but it doesn't hit so the NullPointer is happening on the first time through.
Here is the stacktrace.
java.lang.NullPointerException
at com.revature.data.postgres.CommentPostgres.getAll(CommentPostgres.java:90)
at com.revature.data.CommentDaoTest.getAllNotNull(CommentDaoTest.java:42)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1259)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1259)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:95)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:91)
at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:60)
at org.eclipse.jdt.internal.junit5.runner.JUnit5TestReference.run(JUnit5TestReference.java:98)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:40)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:529)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:756)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:452)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)
Please let me know if you want more files or code snippets added. Thank you for your help.

This line creates a new, empty Comment object:
Comment comment = new Comment();
After that line, you never call comment.setApprover(), so the approver property inside the comment object is null. This doesn't have anything to do with missing data in the database, it is a problem with the way you are initializing your Java objects.
Look at what you are doing here:
comment.getApprover().setEmpId(resultSet.getInt("approver_id"));
You're saying "take the new comment object I just created, get the approver object from it, and then set the ID of that approver". Instead your code needs to look something like this:
Approver approver = getApproverByEmpId(resultSet.getInt("approver_id"));
comment.setApprover(approver);
Where getApproverByEmpId(Integer empId) is a new method you need to create that queries the employee table, and returns an Employee object.

Related

Goerli ValueError: Gas estimation failed: 'execution reverted'

I'm trying to deploy an NFT about Harry Potter following this tutorial: https://www.youtube.com/watch?v=p36tXHX1JD8&list=PLzmffB-8Vx5Twi0x5cRRdzyixrkJtaftJ&index=9&t=3s.
But when I run create_collectible.py I have an error:
ValueError: Gas estimation failed: 'execution reverted'. This transaction will likely revert. If you wish to broadcast, you must set the gas limit manually.
FULL ERROR OUTPUT
File "brownie/_cli/run.py", line 51, in main
return_value, frame = run(
File "brownie/project/scripts.py", line 110, in run
return_value = f_locals[method_name](*args, **kwargs)
File "./scripts/advanced_collectible/create_collectible.py", line 12, in main
transaction = advanced_collectible.createCollectible(
File "brownie/network/contract.py", line 1861, in __call__
return self.transact(*args)
File "brownie/network/contract.py", line 1734, in transact
return tx["from"].transfer(
File "brownie/network/account.py", line 644, in transfer
receipt, exc = self._make_transaction(
File "brownie/network/account.py", line 727, in _make_transaction
raise VirtualMachineError(e) from None
File "brownie/exceptions.py", line 93, in __init__
raise ValueError(str(exc)) from None
ValueError: Gas estimation failed: 'execution reverted'. This transaction will likely revert. If you wish to broadcast, you must set the gas limit manually.
create_collectible.py
from brownie import AdvancedCollectible, accounts, config
from scripts.helpful_scripts import get_raffle, fund_with_link
import time
STATIC_SEED = 1234
def main():
dev = accounts.add(config["wallets"]["from_key"])
advanced_collectible = AdvancedCollectible[len(AdvancedCollectible) - 1]
fund_with_link(advanced_collectible.address)
transaction = advanced_collectible.createCollectible(
STATIC_SEED, "None", {"from": dev}
)
print("Waiting on second transaction...")
# wait for the 2nd transaction
transaction.wait(1)
# time.sleep(35)
requestId = transaction.events["RequestedCollectible"]["requestId"]
token_id = advanced_collectible.requestIdToTokenId(requestId)
raffle = get_raffle(advanced_collectible.tokenIdToRaffle(token_id))
print("Houses of tokenId {} is {}".format(token_id, raffle))
AdvancedCollectible.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "#chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
contract AdvancedCollectible is ERC721URIStorage, VRFConsumerBase {
bytes32 internal keyHash;
uint256 public fee;
uint256 public tokenCounter;
enum Raffle {
GRYFFINDOR,
HUFFLEPUFF,
RAVENCLAW,
SLYTHERIN
}
mapping(bytes32 => address) public requestIdToSender;
mapping(bytes32 => string) public requestIdToTokenURI;
mapping(uint256 => Raffle) public tokenIdToRaffle;
mapping(bytes32 => uint256) public requestToTokenId;
event requestedCollectible(bytes32 indexed requestId);
constructor(
address _VRFCoordinator,
address _LinkToken,
bytes32 _keyhash
) VRFConsumerBase(_VRFCoordinator, _LinkToken) ERC721("Houses", "HOM") {
keyHash = _keyhash;
fee = 0.1 * 10**18; //0.1 LINK
tokenCounter = 0;
}
function createCollectible(string memory tokenURI)
public
returns (bytes32)
{
bytes32 requestId = requestRandomness(keyHash, fee);
requestIdToSender[requestId] = msg.sender; //When I create the request that request is associated with me
requestIdToTokenURI[requestId] = tokenURI;
emit requestedCollectible(requestId);
}
function fulfillRandomness(bytes32 requestId, uint256 randomNumber)
internal
override
{
address wizardOwner = requestIdToSender[requestId];
string memory tokenURI = requestIdToTokenURI[requestId];
uint256 newItemId = tokenCounter;
_safeMint(wizardOwner, newItemId);
_setTokenURI(newItemId, tokenURI);
Raffle raffleHouse = Raffle(randomNumber % 4);
//Need to assign that House raffle to this new token ID
tokenIdToRaffle[newItemId] = raffleHouse;
//Way to map the requestId to the tokenId
requestToTokenId[requestId] = newItemId;
tokenCounter = tokenCounter + 1;
}
function setTokenURI(uint256 tokenId, string memory _tokenURI) public {
require(
_isApprovedOrOwner(_msgSender(), tokenId),
"ERC721: transfer caller is not owner not approved"
);
_setTokenURI(tokenId, _tokenURI);
}
}
brownie-config.yaml
dependencies:
- OpenZeppelin/openzeppelin-contracts#4.7.3
- smartcontractkit/chainlink-brownie-contracts#0.4.2
compiler:
solc:
remappings:
- '#openzeppelin=OpenZeppelin/openzeppelin-contracts#4.7.3'
- '#chainlink=smartcontractkit/chainlink-brownie-contracts#0.4.2'
dotenv: .env
networks:
default: development
goerli:
vrf_coordinator: '0x2Ca8E0C643bDe4C2E08ab1fA0da3401AdAD7734D'
link_token: '0x326C977E6efc84E512bB9C30f76E30c160eD06FB'
keyhash: '0x79d3d8832d904592c0bf9818b621522c988bb8b0c05cdc3b15aea1b6e8db0c15'
fee: 2500000000000000000
wallets:
from_key: ${PRIVATE_KEY}
I'm using alchemy, and re-trying the transaction there works fine. I have no idea why Goerli behaves this way.

spring-data-cassandra-reactive improve performance of ReactiveCrudRepository.save

I have simple showcase with ReactiveCrudRepository, which shows almost 2x difference in insertion speed using ReactiveCrudRepository.save() vs ReactiveCqlOperations.execute()
Here is the code:
Entity:
#Table("snapshot")
#Value
#Builder
#EqualsAndHashCode(callSuper = false)
#RequiredArgsConstructor
public class SnapshotRecord {
#PrimaryKeyColumn(ordinal = 0, type = PrimaryKeyType.PARTITIONED)
long id;
#PrimaryKeyColumn(ordinal = 1, type = PrimaryKeyType.PARTITIONED)
short market;
#PrimaryKeyColumn(ordinal = 3, type = PrimaryKeyType.CLUSTERED)
Instant slot;
double value;
}
Repository:
public interface SnapshotRepository extends ReactiveCrudRepository<SnapshotRecord, Long> {
default Mono<Boolean> saveViaCql(ReactiveCqlOperations cqlOps, SnapshotRecord record) {
return cqlOps.execute(
"INSERT INTO snapshot (id, market,slot,value) VALUES (?,?,?,?) USING TIMESTAMP ?;",
ps -> {
return ps.bind(
record.getId(),
record.getMarket(),
record.getSlot(),
record.getValue(),
record.getSlot().toEpochMilli() * 1000
);
}
);
}
}
Runner:
Flux<SnapshotRecord> data = Flux.generate(Object::new, (state, sink) -> {
ThreadLocalRandom random = ThreadLocalRandom.current();
sink.next(
new SnapshotRecord(
random.nextLong(),
(short) random.nextInt(),
Clock.systemUTC().instant(),
random.nextDouble()
)
);
return state;
});
subscription = data
//.flatMap((SnapshotRecord record) -> repository.saveViaCql(cqlOps, record), 512, 2048)
.flatMap(repository::save, 512, 2048) //doing this runs almost 2x slower than previous line
.doOnNext(d -> success.incrementAndGet())
.onErrorContinue((throwable, object) -> fail.incrementAndGet())
.subscribe();
Full project link on Github:
https://github.com/piddubnyi/spring-data-cassandra-performnace
Is there any way to improve insertion performance of repository.save(), or spring-proxy is really costly in this case?

XG transaction isolation fails during test that generates unique sequence number (Objectify4)

I have to generate a unique invoice number in a XG transaction that includes the following 3 entity groups in my data model :
(toplevel) ContactRoot <-- (ancestor) <--- Contact : contact must be updated to status Client during the transaction
(toplevel) CustomerSettings : holds the next sequence number to use; there is one and only one instance of the CustomerSettings with a fixed, static ID; the sequence number must be increased +1 during the transaction
(toplevel) InvoiceRoot <-- (ancestor) <--- Invoice : assign new unique invoice number based on the sequence number in CustomerSettings;
This is the essential part of the DAO implementation (irrelevant business rules checks etc removed) :
public void saveInvoice(final Invoice invoice) throws BusinessRuleException {
final Objectify ofy = ObjectifyService.factory().begin().cache(true);
ofy.transact(new Work<Void>() {
#Override
public Void run() {
CustomerSettings customerSettings = ofy.load()
.key(Key.create(CustomerSettings.class, CustomerSettings.ID)).safeGet();
Contact contact = ofy.load().key(createContactKey(invoice.getContactId()).safeGet();
contact.setContactType(ContactType.CLIENT);
ofy.save().entity(contact).now();
String invoiceNumber = generateSequence(ofy, customerSettings);
invoice.setInvoiceNumber(invoiceNumber);
ofy.save().entity(invoice).now();
return null;
}
});
}
And the simplified version to generate the next sequence number where the next sequence number is increased for the next call and the CustomerSettings must be transactionally updated (I have this synchronized but I guess that is not really useful)
:
private synchronized String generateSequence(Objectify ofy, CustomerSettings settings) {
String ret = "";
int sequence = settings.getNextSequence();
settings.setNextSequence(sequence + 1);
ofy.save().entity(settings).now();
ret = "" + sequence;
return ret;
}
This is what my unit test looks like for a variable thread count :
private void test(final int threadCount) throws InterruptedException, ExecutionException {
final Environment currentEnvironment = ApiProxy.getCurrentEnvironment();
Callable<String> task = new Callable<String>() {
#Override
public String call() {
ApiProxy.setEnvironmentForCurrentThread(currentEnvironment);
return generateInvoiceNumber();
}
};
List<Callable<String>> tasks = Collections.nCopies(threadCount, task);
ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
List<Future<String>> futures = executorService.invokeAll(tasks);
List<String> resultList = new ArrayList<String>(futures.size());
// Check for exceptions
for (Future<String> future : futures) {
// Throws an exception if an exception was thrown by the task.
resultList.add(future.get());
}
// Validate the IDs
Assert.assertEquals(futures.size(), threadCount);
List<String> expectedList = new ArrayList<String>(threadCount);
for (long i = 1; i <= threadCount; i++) {
expectedList.add("" + i);
}
Collections.sort(resultList);
Assert.assertEquals(expectedList, resultList);
}
#SuppressWarnings("unchecked")
private String generateInvoiceNumber() {
InvoiceDAO invoiceDAO = new InvoiceDAO();
Invoice invoice = ... create a valid invoice
invoiceDAO.saveInvoice(invoice);
log.info("generated invoice number : " + invoice.getInvoiceNumber());
return invoice.getInvoiceNumber();
}
for instance when I run this with 32 threads simultaneous :
#Test
public void test32() throws InterruptedException, ExecutionException {
test(32);
}
But subsequent threads do not see that a previous transaction increased the invoice number sequence.
This is the result :
junit.framework.AssertionFailedError: expected:<[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32]> but was:<[1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3,
3]>
I went through the docs already a couple of times, can't figure out why this is not working ?
If you access more than one entity group in a transaction, the
transaction with be an XG transaction. If you do access only one, it
is not. The standard limit of 5 EGs applies to all transactions.
objectify transactions documentation
what am I doing wrong ?
This piece of code make the code not transactional :
final Objectify ofy =
ObjectifyService.factory().begin().cache(true);
ofy.transact(new Work<Void>() {
....
ofy.save().entity(settings).now();
....
}
because I reuse the objectify instance that is not transactional. To get the instance inside the transaction Work, you must always ask the instance like this :
ObjectifyService.ofy()
more info in the group discussion here.
Looking at the implementation of ObjectifyService, you can see that new instances are pushed/popped onto/from a stack;
Apart from that, the test case is still not running .. the best way to test is presumably firing http requests simulataneous;

Exception in thread "Thread-4" java.lang.NullPointerException?

i have a problem with this exception.
I'm trying to make a function to display data from database on a table, every keystroke i made at jtextfield. So its like the table automatically refreshed with new data everytime i type in the jtextfield.
Here's the code :
First i have this variable :
private Statement stmt;
List<Barang> dataSBarang =new LinkedList();
boolean searchBarang=true;
Searching sBarang;
And this is how i call the function :
private void inputkodeTFMouseClicked(java.awt.event.MouseEvent evt){
sBarang = new Searching( stmt, dataSBarang, modelDetail, tabelDetailBarang, inputkodeTF, searchBarang);
sBarang.start();
}
And this is the Searching Object
public class Searching extends Thread{
private Statement stmt;
private List<Barang> dataBarang;
private JTable jTabelBarang;
private JTextField tf;
private boolean cari;
private DefaultTableModel modelBarang;
public Searching(Statement stmt, List<Barang> dataBarang, DefaultTableModel tm, JTable jTabelBarang, JTextField tf, boolean cari){
this.stmt=stmt;
this.dataBarang=dataBarang;
this.modelBarang=tm;
this.jTabelBarang=jTabelBarang;
this.tf=tf;
this.cari=cari;
}
#Override
public void run(){
String temp="";
while(cari==true){
//System.out.println("jalan");
try{
String masukan = tf.getText();
System.out.println(masukan);
if(!masukan.equals("")&&!masukan.equals(temp)){
clearTableBarang();
//System.out.println("Mencari "+ masukan);
ResultSet rs = stmt.executeQuery("select kode_barang, nama_barang, jumlah_stok, " +
"minimal_stok, harga_jual, deskripsi_barang from BARANG WHERE (kode_barang LIKE " +
"'"+masukan+"%')");
System.out.println(rs);
while(rs.next()){
String kode_barang = rs.getString ("kode_barang");
String nama_barang = rs.getString ("nama_barang");
int jumlah_stok = rs.getInt("jumlah_stok");
int minimal_stok = rs.getInt("minimal_stok");
int harga_jual = rs.getInt("harga_jual");
String deskripsi_barang = rs.getString ("deskripsi_barang");
//System.out.println(kode_barang+" "+deskripsi_barang);
dataBarang.add(new Barang(kode_barang,nama_barang,jumlah_stok,minimal_stok,harga_jual,deskripsi_barang));
((DefaultTableModel) jTabelBarang.getModel()).insertRow(jTabelBarang.getRowCount(), new Object[]{kode_barang, nama_barang, jumlah_stok, minimal_stok, harga_jual, deskripsi_barang});
}
temp = masukan;
}
else if(masukan.equals("")&&!masukan.equals(temp)) {
clearTableBarang();
showTableBarang();
temp = masukan;
}
} catch(SQLException s){s.printStackTrace();}
catch(ArrayIndexOutOfBoundsException s){s.printStackTrace();}
try {
sleep(500);
} catch(InterruptedException e){}
}
}
public void clearTableBarang(){
int numrows = modelBarang.getRowCount();
for(int i = numrows - 1; i >=0; i--){
modelBarang.removeRow(i);
}
dataBarang.clear();
}
public void showTableBarang(){
try{
ResultSet rs = stmt.executeQuery("select kode_barang, nama_barang, jumlah_stok, minimal_stok, harga_jual, deskripsi_barang from barang");
while(rs.next()){
String kode_barang = rs.getString ("kode_barang");
String nama_barang = rs.getString ("nama_barang");
int jumlah_stok = rs.getInt("jumlah_stok");
int minimal_stok = rs.getInt("minimal_stok");
int harga_jual = rs.getInt("harga_jual");
String deskripsi_barang = rs.getString ("deskripsi_barang");
//System.out.println(kode_barang+" "+deskripsi_barang);
dataBarang.add(new Barang(kode_barang,nama_barang,jumlah_stok,minimal_stok,harga_jual,deskripsi_barang));
((DefaultTableModel)jTabelBarang.getModel()).insertRow(jTabelBarang.getRowCount(), new Object[]{kode_barang, nama_barang, jumlah_stok, minimal_stok, harga_jual, deskripsi_barang});
}
} catch(SQLException s){s.printStackTrace();}
}
public void delay(){
try {
sleep(1000000000);
} catch(InterruptedException e){}
}
}
This is the error :
Exception in thread "Thread-4" java.lang.NullPointerException
at mypkg.Searching.run(Searching.java:47)
FYI : Line 47 is pointing to
ResultSet rs = stmt.executeQuery("select kode_barang, nama_barang, jumlah_stok, " +
"minimal_stok, harga_jual, deskripsi_barang from BARANG WHERE (kode_barang LIKE " +
"'"+masukan+"%')");
Please help me solve the problem. Thank you very much. :D
NullPointerExceptions are the most easy ones to fix with a debugger. Just place a breakpoint on that line and see what is null.
If the line you posted is correct, you do not even need a debugger since the only thing that can throw the exception is stmt which will be null.
Note:
It is a good thing to run your DB query in a separate Thread to avoid blocking the UI. However, in your case you are updating the UI from that Thread which is not allowed and will cause weird issues. All Swing components must be accessed on the Event Dispatch Thread (EDT). Consult the Swing concurrency tutorial for more information
I do hope you are not starting up a separate Thread on each keystroke in the textfield as you indicated in your question. Looking at the code in the Thread, you remove all elements from the table and then re-add rows. So if a users types in 5 characters at a normal typing speed, you will launch 5 threads which most likely run all at the same time (since a DB connection might not be that fast if your network is lagging). That means that with your current code 5 Threads are, at the same time, removing the table model and adding rows. Even if you put all the Swing code on the EDT (see my first point), you still end up with 5 threads posting runnables on the EDT messing with your table model. I do not know what the resulting table model will be, but probably not what you want
Clearly stmt is null.
You declare it here:
private Statement stmt;
List<Barang> dataSBarang =new LinkedList();
boolean searchBarang=true;
Searching sBarang;
But I don't see any initialization code anywhere, so most likely it remains null for this method call:
private void inputkodeTFMouseClicked(java.awt.event.MouseEvent evt){
sBarang = new Searching( stmt, dataSBarang, modelDetail, tabelDetailBarang, inputkodeTF, searchBarang);
sBarang.start();
}

Get count of an IQueryable<T>

Assume we have the following collection
IEnumerable<int> list = new List<int> { 11, 12, 13, 14, 15, 16, 17, 18, 19, 10 };
var query = list.Skip(5).Take(4);
SomeMethod(query.AsQueryable());
.
.
.
public void SomeMethod(IQueryable<T> query)
{
var collectionCount = ????? // count should be 10 not 4.
...
}
How can I get the count of the original collection (without applying Skip and Take sub-queries) of the query in the SomeMethod.
Thanks.
There is no way you could get the information (except maybe by doing some hardcore reflection stuff). It is simply not there anymore. It’s like you wanted to extract the original count from something like this:
var list = new List<int> { 11, 12, 13, 14, 15, 16, 17, 18, 19, 10 };
SomeMethod(list[3]);
public void SomeMethod(int number)
{
var collectionCount = ????? // count should be 10
...
}
I think you might be able to get the information if instead of IQueryable, you would pass Expression, however, even this case would not be simple.
Added per comments:
It is not as simple as you might think; I don’t even think it is possible fully generally. However, for some limited use cases it might work. I have quickly hacked a method which “removes” any Skip a Take applied to the query and returns the original count. Give it a try, YMMV:
public int CountOriginal<T>(IQueryable<T> query)
{
var ex = query.Expression;
while (ex.NodeType == ExpressionType.Call)
{
var call = (MethodCallExpression)ex;
if (call.Method.Name != "Skip" && call.Method.Name != "Take") break;
ex = call.Arguments[0];
}
var enumerable = Expression.Lambda(ex).Compile().DynamicInvoke(null) as IEnumerable<T>;
if (enumerable == null) throw new NotImplementedException();
return enumerable.Count();
}
list.Count should return the count of the original list

Resources