Postgres JDBC fetchSize() ignored - postgresql

Why I'm having the fetch size ignored, I set it to 2, but whenever I run the program it returns whole records! If I print the fetch size will print 2, but the result will return whole records. Any implementation that I can return rows according to the fetch size? i.e I have 10 records in my DB I need to return 2 records for each trip in my tableAsStream method?
private Stream<SecurityGroup> tableAsStream(Context context, Connection connection) throws SQLException {
try {
connection.setAutoCommit(false);
Statement statement = connection.createStatement();
statement.setFetchSize(FETCH_SIZE);
ResultSet resultSet = statement.executeQuery(SELECT_SCHEDULE_MODULES_QUERY);
log.info("Returning a stream of SecurityGroups from the prepared statement ");
return StreamSupport.stream(new Spliterators.AbstractSpliterator<SecurityGroup>(Long.MAX_VALUE, Spliterator.ORDERED) {
#Override
public boolean tryAdvance(Consumer<? super SecurityGroup> action) {
try {
if(!resultSet.next()) return false;
action.accept(createRecord(resultSet));
return true;
} catch(SQLException ex) {
throw new RuntimeException(ex);
}
}
}, false);
} catch(SQLException sqlEx) {
throw sqlEx;
}
}
public void migrate(Context context) throws Exception {
Connection connection = context.getConnection();
// do{
log.info("Migration script started for (SCHEDULE_SHIFTS_EDIT_SELF).");
List<SecurityGroup> securityGroupList = tableAsStream(context, connection).collect(Collectors.toList());
securityGroupList.stream()
.flatMap(securityGroup -> securityGroup.getModules().stream())
.filter(securityModule -> securityModule.getName() == ModuleName.SCHEDULE)
.forEach(filteredSecurityModule -> {
boolean editPermissionExists = filteredSecurityModule.getFeatures().stream()
.anyMatch(x->PermissionName.SCHEDULE_SHIFTS_EDIT == x.getName());
boolean editSelfPermissionExists = filteredSecurityModule.getFeatures().stream()
.anyMatch(x->PermissionName.SCHEDULE_SHIFTS_EDIT_SELF == x.getName());
if (editPermissionExists && !editSelfPermissionExists) {
filteredSecurityModule.getFeatures().add(SecurityFeature.of(PermissionName.SCHEDULE_SHIFTS_EDIT_SELF, true, false));
}
});
updateSecurityGroups(securityGroupList, context);
log.info("Migration script Ended for (SCHEDULE_SHIFTS_EDIT_SELF).");
// } while(condition);
}

Related

Rare error when trying to save data "unhandled exception on the current circuit"

I am using VS 2022, Blazor server project. When I trying to save data
async public static Task<bool> updateObject(Firecall obj)
{
Firecall r;
try
{
using (var context = new sptContext())
{
r = context.Firecalls.Where(c => c.Mguid == obj.Mguid).FirstOrDefault();
bool новое = (r == null);
if (новое)
{
r = new Firecall();
}
r.comment = obj.comment;
if (новое)
await context.Firecalls.AddAsync(r);
if (busy)
return false;
try
{
busy = true;
await context.SaveChangesAsync();
}
catch (Exception)
{
return false;
}
finally {
busy = false;
}
}
return true;
}
catch (Exception)
{
return false;
}
}
sometimes I get error:
Sometimes an error occurs, sometimes not. No error in debugger.
How to solve problem?
P.S. Data in each operation is saved as expected. Only after the operation is completed the indicated error message appear
And calling savechanges method from #code block of .razor view:
async private void SaveChanges()
{
bool rez = await firecallRepository.updateObject(_currentFireCall);
}

RxJava Problem with reading a file with Observable and take operator

My working environment is JDK 1.6 and RxJava 2
I want to make an Observable which emits an item that is a file line string read via BufferedReader as follows:
...
Observable<String> fileLineObservable = Observable.defer(new Callable<String>(){
return new ObservableSource<String> call() throws Exception {
return new ObservableSource<String>() {
public void subscribe(Observer<String> observer) {
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(filePath));
String line = null;
while ((line = reader.readLine()) != null) {
observer.onNext(line);
}
observer.onComplete();
... catching exception and close reader
}
}
}
}
});
I also want to make an Observer that observes the above Observable with one take(count) operator as follows:
fileLineObservable.take(2)
.subscribe(new Consumer<String>() {
public void onNext(String line) {
... do something with the file line string
}
});
I meet NullPointerException when executing the above code and I know why. The NPE is caused by that the second call of onNext leads to execute onComplete on the TakeObserver instance and inside the onComplete method, upstream.dispose that is not set(null) is called. The upstream variable of TakeObserver is supposed to be set with onSubscribe(Disposable disposable) when it subscribes an Observable.
How can I solve this problem? Should I implement my own Disposable class to set the upstream of TakeObserver?
What about this solution?
Observable<String> observableFile2(Path path) {
return Observable.using(
() -> Files.newBufferedReader(path),
reader -> {
return Observable.fromIterable(() -> {
return new Iterator<>() {
private String nextLine = null;
#Override
public boolean hasNext() {
try {
nextLine = reader.readLine();
return nextLine != null;
} catch (Exception ex) {
return false;
}
}
#Override
public String next() {
if (nextLine != null) {
return nextLine;
}
throw new IllegalStateException("nextLine can not be null.");
}
};
});
},
BufferedReader::close
);
}
Observable#using makes sure, that the BufferedReader is closed properly on disposable / onError
Observable#fromIterable wraps the readLine calls and handles onComplete for us.
Testing
testImplementation("org.junit.jupiter:junit-jupiter-api:5.6.2")
testRuntimeOnly("org.junit.platform:junit-platform-launcher:1.6.2")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.6.2")
testRuntimeOnly("org.junit.vintage:junit-vintage-engine:5.6.2")
testImplementation("com.google.jimfs:jimfs:1.1")
Tests
#Test
void name() {
observableFile2(hello).take(2)
.test()
.assertValues("line0", "line1")
.assertComplete();
}
#Test
void name2() {
observableFile2(hello).take(10)
.test()
.assertValues("line0", "line1", "line2", "line3")
.assertComplete();
}
#Test
void name3() {
observableFile2(hello2)
.test()
.assertComplete();
}

PostgreSQL JDBC transaction isolation

I have these two operations:
public class Car {
...
public void delete() throws SQLException {
Connection c = Db.getConnection();
c.setAutoCommit(false);
if (c.getTransactionIsolation() == 0) {
c.setTransactionIsolation(c.TRANSACTION_READ_COMMITTED);
}
String sql = "DELETE FROM cars WHERE id = ?";
try(PreparedStatement s = c.prepareStatement(sql)) {
s.setInt(1, id);
s.executeUpdate();
c.commit();
}
}
}
and second one:
public class CarTransfer {
public static boolean transfer(int person_id, int car_id, int other_shop_id) throws SQLException, Exception {
Car car = FindCar.getInstance().findById(car_id);
Person person = FindPerson.getInstance().findById(person_id);
try {
if (car == null) {
throw new CallException("Car doesn't exist");
}
} catch (CallException e) {
System.out.println(e.getMessage());
}
Connection c = Db.getConnection();
c.setAutoCommit(false);
if (c.getTransactionIsolation() == 0) {
c.setTransactionIsolation(c.TRANSACTION_READ_COMMITTED);
}
String sql = "";
try {
sql = "UPDATE car_belongs_shop SET shop_id = "+other_shop_id+" WHERE car_id = "+car.getId();
} catch (NullPointerException e) {
System.out.println("Did not find a car / shop");
return false;
}
try(PreparedStatement s = c.prepareStatement(sql)) {
s.executeUpdate();
try {
if (person.getCredit() < 100) {
c.rollback();
throw new CallException("Not enough credit");
}
else {
if (car == null) {
c.rollback();
throw new CallException("Car doesn't exist");
}
else {
c.commit();
person.buy(100);
}
}
} catch (CallException | NullPointerException e) {
System.out.println(e.toString());
return false;
}
}
c.setAutoCommit(true);
return true;
}
}
So what I want to do is to transfer a car from one shop to another. But in that time, some other transaction can be done on the other side, when someone removes that car from database (that's first method delete()). What I want to do is to block any delete() method in the time when transfer is running. I'm trying to do that by this code, and it's transaction isolation (in level read committed). However, this does not work as intended, because it's still possible to remove a car whilst transfer method is running. Can you help me, whether I use sufficient isolation level or have whole transactions in the right place of the code?

Master -Slave Database Configuration With Hikari Pool

I have two DataSource Beans one with #Primary annotation.
Individual Hikari pools are created for every DataSource.
I am trying to change the HikariDataSource from Pool 1(if connection is not available) to Pool 2 .
#Primary
#Bean(destroyMethod = "close", name = "dataSource")
public CustomHikariDataSource dataSource() throws SQLException {
try {
primaryDataSource = mainDataSource();
} catch (Exception e) {
primaryDataSource = secondaryDataSource();
}
HikariConfig config = new HikariConfig();
config.setDataSource(primaryDataSource);
config.setPoolName("POOL_PRIMARY");
config.setAllowPoolSuspension(true);
config.setIdleTimeout(10000);
config.setMaxLifetime(30000);
return new CustomHikariDataSource(config);
}
#Bean(destroyMethod = "close", name = "failoverDataSource")
public CustomHikariDataSource failoverDataSource() throws SQLException {
secondaryDataSource = secondaryDataSource();
HikariConfig config = new HikariConfig();
config.setDataSource(secondaryDataSource);
config.setPoolName("POOL_SECONDARY");
config.setAllowPoolSuspension(true);
return new CustomHikariDataSource(config);
}
private DataSource mainDataSource() {
return dataSourceProperties().initializeDataSourceBuilder().build();
}
private DataSource secondaryDataSource() {
return failoverDataSourceProperties().initializeDataSourceBuilder().build();
}
Where is the actual Problem?
Finally i am able to achieve it by Overriding getConnection() method from HikariDataSource.class
#Override
public Connection getConnection() throws SQLException {
if (isClosed()) {
throw new SQLException("HikariDataSource " + this + " has been closed.");
}
if (fastPathPool != null && (fastPathPool.poolState == 0 || fastPathPool.poolState == 1)) {
try {
fastPathPool.resumePool();
con = fastPathPool.getConnection();
} catch (Exception e) {
}
if (con.isClosed()) {
config = pool.config;
fastPathPool.suspendPool();
} else
return con;
}
config.setDataSource(dataSource);
config.setAllowPoolSuspension(true);
config.setMinimumIdle(minIdle);
pool = new HikariPool(config);
HikariPool result = pool;
if (result == null) {
synchronized (this) {
result = pool;
if (result == null) {
validate();
System.out.println("{} - Starting..." + getPoolName());
try {
pool = result = new HikariPool(this);
this.seal();
} catch (PoolInitializationException pie) {
if (pie.getCause() instanceof SQLException) {
throw (SQLException) pie.getCause();
} else {
throw pie;
}
}
System.out.println("{} - Start completed." + getPoolName());
}
}
}
return result.getConnection();
}
For complete class ,feel free to ping me.
Happy Coding ! :)

Show previous instance of RCP application

I had an rcp application which runs for only first run, when a user attempts to re-execute the application, second instance behaves as a client which encodes and sends its arguments over the socket to the first instance which acts as a server and then exits silently. The first instance receives and decodes that message, then behaves as if it had been invoked with those arguments.
so far so good i made internal protocol specification for passing arguments between two instances.
I could not bring the first instance(RCP application) to front. It is in minimized state only,
this is in continuation to my previous question
the change i made to previous post is start method of application class
public Object start(IApplicationContext context) throws Exception {
if (!ApplicationInstanceManager.registerInstance()) {
return IApplication.EXIT_OK;
}
ApplicationInstanceManager
.setApplicationInstanceListener(new ApplicationInstanceListener() {
public void newInstanceCreated() {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
System.out.println("New instance detected...");
//Display.getCurrent().getActiveShell()
.forceActive();// this gives null
// pointer exception
// hence commented
}
});
}
});
Display display = PlatformUI.createDisplay();
try {
int returnCode = PlatformUI.createAndRunWorkbench(display,
new ApplicationWorkbenchAdvisor());
if (returnCode == PlatformUI.RETURN_RESTART)
return IApplication.EXIT_RESTART;
else
return IApplication.EXIT_OK;
} finally {
display.dispose();
}
}
below line is stopping me to bring Application to front
Display.getCurrent().getActiveShell().forceActive();
generates null pointer exception at getActiveShell()
how can i maximize the previous instance or bring it to front
I wrote an instance manager to restrict my RCP to a single instance.
Here's the code that goes in Application.java, in the start method:
if (!ApplicationInstanceManager.registerInstance()) {
return IApplication.EXIT_OK;
}
ApplicationInstanceManager
.setApplicationInstanceListener(new ApplicationInstanceListener() {
public void newInstanceCreated() {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
if (DEBUG)
System.out.println("New instance detected...");
Display.getCurrent().getActiveShell().forceActive();
}
});
}
});
Here's the listener interface:
public interface ApplicationInstanceListener {
public void newInstanceCreated();
}
And here's the Manager class:
public class ApplicationInstanceManager {
private static final boolean DEBUG = true;
private static ApplicationInstanceListener subListener;
/** Randomly chosen, but static, high socket number */
public static final int SINGLE_INSTANCE_NETWORK_SOCKET = 44331;
/** Must end with newline */
public static final String SINGLE_INSTANCE_SHARED_KEY = "$$RabidNewInstance$$\n";
/**
* Registers this instance of the application.
*
* #return true if first instance, false if not.
*/
public static boolean registerInstance() {
// returnValueOnError should be true if lenient (allows app to run on
// network error) or false if strict.
boolean returnValueOnError = true;
// try to open network socket
// if success, listen to socket for new instance message, return true
// if unable to open, connect to existing and send new instance message,
// return false
try {
final ServerSocket socket = new ServerSocket(
SINGLE_INSTANCE_NETWORK_SOCKET, 10, InetAddress
.getLocalHost());
if (DEBUG)
System.out
.println("Listening for application instances on socket "
+ SINGLE_INSTANCE_NETWORK_SOCKET);
Thread instanceListenerThread = new InstanceListenerThread(socket);
instanceListenerThread.start();
// listen
} catch (UnknownHostException e) {
EclipseLogging.logError(RabidPlugin.getDefault(),
RabidPlugin.PLUGIN_ID, e);
return returnValueOnError;
} catch (IOException e) {
return portTaken(returnValueOnError, e);
}
return true;
}
private static boolean portTaken(boolean returnValueOnError, IOException e) {
if (DEBUG)
System.out.println("Port is already taken. "
+ "Notifying first instance.");
try {
Socket clientSocket = new Socket(InetAddress.getLocalHost(),
SINGLE_INSTANCE_NETWORK_SOCKET);
OutputStream out = clientSocket.getOutputStream();
out.write(SINGLE_INSTANCE_SHARED_KEY.getBytes());
out.close();
clientSocket.close();
System.out.println("Successfully notified first instance.");
return false;
} catch (UnknownHostException e1) {
EclipseLogging.logError(RabidPlugin.getDefault(),
RabidPlugin.PLUGIN_ID, e);
return returnValueOnError;
} catch (IOException e1) {
EclipseLogging
.logError(
RabidPlugin.getDefault(),
RabidPlugin.PLUGIN_ID,
"Error connecting to local port for single instance notification",
e);
return returnValueOnError;
}
}
public static void setApplicationInstanceListener(
ApplicationInstanceListener listener) {
subListener = listener;
}
private static void fireNewInstance() {
if (subListener != null) {
subListener.newInstanceCreated();
}
}
public static void main(String[] args) {
if (!ApplicationInstanceManager.registerInstance()) {
// instance already running.
System.out.println("Another instance of this application "
+ "is already running. Exiting.");
System.exit(0);
}
ApplicationInstanceManager
.setApplicationInstanceListener(new ApplicationInstanceListener() {
public void newInstanceCreated() {
System.out.println("New instance detected...");
// this is where your handler code goes...
}
});
}
public static class InstanceListenerThread extends Thread {
private ServerSocket socket;
public InstanceListenerThread(ServerSocket socket) {
this.socket = socket;
}
#Override
public void run() {
boolean socketClosed = false;
while (!socketClosed) {
if (socket.isClosed()) {
socketClosed = true;
} else {
try {
Socket client = socket.accept();
BufferedReader in = new BufferedReader(
new InputStreamReader(client.getInputStream()));
String message = in.readLine();
if (SINGLE_INSTANCE_SHARED_KEY.trim().equals(
message.trim())) {
if (DEBUG)
System.out.println("Shared key matched - "
+ "new application instance found");
fireNewInstance();
}
in.close();
client.close();
} catch (IOException e) {
socketClosed = true;
}
}
}
}
}
}
After your IApplication start up, you can also check and lock the OSGi instance location using org.eclipse.osgi.service.datalocation.Location.isSet() and org.eclipse.osgi.service.datalocation.Location.lock()
The location is usually retrieved from your Activator using code like:
public Location getInstanceLocation() {
if (locationTracker == null) {
Filter filter = null;
try {
filter = context.createFilter(Location.INSTANCE_FILTER);
} catch (InvalidSyntaxException e) {
// ignore this. It should never happen as we have tested the
// above format.
}
locationTracker = new ServiceTracker(context, filter, null);
locationTracker.open();
}
return (Location) locationTracker.getService();
}