MySql : Multi-Threaded JdbcTemplate is throwing a NullPointerException - spring-jdbc

jdbctemplate is throwing an error in a Multi-Threaded environment.
I'm using jdbctemplate for inserting data into MySql dB.
I am sending a list of User objects to jdbcTemplate.batchUpdate. Can see the values in the DbDAO constructor and run() method, but jdbcTemplate.batchUpdate is throwing a null pointer exception.
#Repository
public class DbDAO implements Runnable {
#Qualifier("jdbcDb")
#Autowired
JdbcTemplate jdbcTemplate;
public String query;
public ArrayList<User> users;
public DbDAO() {
}
public DbDAO(final String query, final ArrayList<User> users) {
this.query = query;
this.users = (ArrayList<User>) users.clone();
System.out.println("## In DbDAO Constructor ##\n" + "Query: " + query + " Users: " + users.toString());
}
#Override
public void run() {
System.out.println(
Thread.currentThread().getId() + " In run **\n" + "Query: " + query + " Users: " + users.toString());
try {
jdbcTemplate.batchUpdate(query, new BatchPreparedStatementSetter() {
#Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
User user = users.get(i);
ps.setLong(2, user.getUserId());
ps.setString(3, user.getUserName());
ps.setString(4, user.getUserAddress());
}
#Override
public int getBatchSize() {
return users.size();
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}
Exception
Query: insert into users (id, name, address) values (?, ?, ?) Users:
[User [userName=Name, userId=81, userAddress=Address], User
[userName=Name, userId=82, userAddress=Address], User [userName=Name,
userId=83, userAddress=Address], User [userName=Name, userId=84,
userAddress=Address] ]
at com.ronan.DbDAO.run(DbDAO.java:52)
at
java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at
java.util.concurrent.ThreadPoolExecutor.runWorker
(ThreadPoolExecutor.java:1149)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run
(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
java.lang.NullPointerException
at com.ronan.DbDAO.run(DbDAO.java:52)
at
java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)

Found out what the issue was, sometime back. Just wanted to post this answer, so that it might be useful to someone.
Issue was with the Datasource configuration. Fixed that. :
#Bean(name="dbone")
public DataSource createDbDatasource() {
DriverManagerDataSource dataSource = new
DriverManagerDataSource();
dataSource.setUrl(datasourceOneUrl);
return dataSource;
}
#Bean(name="jdbcDb")
#Autowired
public JdbcTemplate createJdbcTemplate(#Qualifier("dbone")
DataSource dbOneDS) {
return new JdbcTemplate(dbOneDS);
}

Related

Retrofit2 ApiServices savepoint showing null object reference

DetailFragment.java
public void sendPost() {
mAPIService.savePost("O3", 2, "ssfu", "jhsgdhf", 20, "mystring", 1, "UnoiaTech", "hdbjhsdhfjsd").enqueue(new Callback<Post>() {
#Override
public void onResponse(Call<Post> call, Response<Post> response) {
if (response.isSuccessful()) {
Toast.makeText(getActivity(), "Submited" + response.body(), Toast.LENGTH_SHORT).show();
Log.i(TAG, "post submitted to API." + response.body().toString());
}
}
#Override
public void onFailure(Call<Post> call, Throwable t) {
Toast.makeText(getActivity(), "Error To Post API in DetailFragment", Toast.LENGTH_SHORT).show();
Log.e(TAG, "Unable to submit post to API.");
}
});
}
PlanFragment.java
next_plan_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
detailFragment.sendPost();
}
});
ApiUtils.java
public class ApiUtils {
private ApiUtils() {}
public static final String BASE_URL = "http://192.168.100.14:8080";
public static APIService getAPIService() {
return RetrofitClient.getClient(BASE_URL).create(APIService.class);
}
}
RetroClient.java
public class RetrofitClient {
private static Retrofit retrofit = null;
public static Retrofit getClient(String baseUrl) {
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
ApiService.java
public interface APIService {
#POST("/deals/deal")
#FormUrlEncoded
Call<Post> savePost(#Field("bookingType") String bookingType,
#Field("dealPrice") int dealPrice,
#Field("description") String description,
#Field("keyword") String keyword,
#Field("originalPrice") int originalPrice,
#Field("plan") String plan,
#Field("shopId") int shopId,
#Field("shopName") String shopName,
#Field("title") String title);
}
Showing error
FATAL EXCEPTION: main
Process: googlemap.arun.com.mywork2, PID: 20969
java.lang.NullPointerException: Attempt to invoke interface method
'retrofit2.Call
googlemap.arun.com.mywork2.data.remote.APIService.savePost(java.lang.String,
int, java.lang.String, java.lang.String, int, java.lang.String, int,
java.lang.String, java.lang.String)' on a null object reference
at
googlemap.arun.com.mywork2.DetailFragment.sendPost(DetailFragment.java:104)
at
googlemap.arun.com.mywork2.PlanFragment$5.onClick(PlanFragment.java:85)
at android.view.View.performClick(View.java:5272)
at android.view.View$PerformClick.run(View.java:21528)
at android.os.Handler.handleCallback(Handler.java:815)
at android.os.Handler.dispatchMessage(Handler.java:104)
at android.os.Looper.loop(Looper.java:207)
at android.app.ActivityThread.main(ActivityThread.java:5857)
at java.lang.reflect.Method.invoke(Native Method)
at
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1026)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:887)

springboot websocket with JPA NullPointerException

I'm wreting a SpringBoot web service use websocket to send message to client and using JPA to save data.
in project I use a thread to create a data ,and then use JPA to save it ,use Websocket to show data. But it doesn't work with a NullPointExecption.
this is my code:
#RestController
#ServerEndpoint("/websocket")
public class CrawlingController {
private final Logger logger = LoggerFactory.getLogger(CrawlingController.class);
#Autowired
private SimulateDataRepository simulateDataRepository;
private static GlobalStatus globalStatus = GlobalStatus.getInstance();
private Session session;
private static CopyOnWriteArraySet<CrawlingController> crawlingControllers =
new CopyOnWriteArraySet<>();
#OnOpen
public void onOpen(Session session) throws Exception {
this.session = session;
crawlingControllers.add(this);
String message = dataCrawling();
}
#OnMessage
public void onMessage(String message, Session session) throws IOException {
for (CrawlingController controller : crawlingControllers)
sendMessage(message);
}
#OnClose
public void onClose() {
crawlingControllers.remove(this);
if (crawlingControllers.size() == 0)
end();
session=null;
end();
}
private void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
}
public void onError(Session session, Throwable error) {
logger.error(error.getMessage());
System.out.println("websocket found something error!");
}
#RequestMapping("/start")
public String dataCrawling() throws Exception {
if (!globalStatus.isDataCrawling) {
Process process = null;
synchronized (globalStatus) {
process = Utils.crawling();
globalStatus.crawlingProcss = process;
globalStatus.isDataCrawling = true;
}
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
new Thread(() -> {
try {
stuffSimulate(bufferedReader);
} catch (IOException | ParseException e) {
logger.error(e.getMessage());
}
}).start();
return "start Finish!";
} else return "faild";
}
public void stuffSimulate(BufferedReader reader) throws IOException, ParseException {
line = reader.readLine();
while (globalStatus.isDataCrawling) {
SimulateData simulateData = new SimulateData();
.... ...
simulateData.setData(data.toString());
this.saveAndShow(simulateData);
}
}
}
}
private void saveAndShow(SimulateData simulateData) throws IOException {
simulateData = simulateDataRepository.saveAndFlush(simulateData);
SummaryData summaryData = SimulateService.obtainSummary(simulateData);
onMessage(summaryData.printSummary(),this.session);
summaryData.sout();
}
}
simulateDataRepository can be work when i use http://localhost:8080/start.
the mysql can get data.
But it cna't be work when i use websocket!!!
The error meaasge said that:
Exception in thread "Thread-5" java.lang.NullPointerException
at cn.linhos.controller.CrawlingController.saveAndShow(CrawlingController.java:293)
at cn.linhos.controller.CrawlingController.stuffSimulate(CrawlingController.java:172)
at cn.linhos.controller.CrawlingController.lambda$dataCrawling$0(CrawlingController.java:104)
at java.lang.Thread.run(Thread.java:748)
why simulateDataRepository can't saveAndFlush when websocket but can do it when i use "/start"?
how should i do to make websocket work ?

getting error on createObject

i am getting
StartSensor Attempt to invoke virtual method 'void io.realm.ProxyState.setConstructionFinished()' on a null object reference
i try to create a new object with primarykey inside application class.
primarykeyFactory works it set the new key to "1" the database is empty at this moment.
public class SensorRecord extends MainApplication {
private final static String TAG = SensorRecord.class.getSimpleName();
private Realm mRealm;
public SensorRecord() {
Realm.init(this);
mRealm = getInstance(getRealmConfig());
}
public void StartSensor(long startTime) {
long newprimekey = PrimaryKeyFactory.getInstance().nextKey(SensorData.class);
try {
mRealm.beginTransaction();
SensorData mSensorData = mRealm.createObject(SensorData.class, newprimekey);
mSensorData.setstarted_at(startTime);
mRealm.commitTransaction();
mRealm.close();
} catch (Exception e) {
Log.v(TAG, "StartSensor " + e.getMessage());
}
}}
my main application class which init the realm config
public class MainApplication extends RealmBaseApplication {
private final static String TAG = MainApplication.class.getSimpleName();
Realm mRealm;
#Override
public void onCreate() {
super.onCreate();
Realm.init(this);
mRealm = getInstance(getRealmConfig());
initializePrimaryKeyFactory();
}
public void initializePrimaryKeyFactory() {
try {
Log.v(TAG, "Start PrimaryKeyFactory ");
PrimaryKeyFactory.getInstance().initialize(mRealm);
} catch (Exception e) {
Log.v(TAG, "initializePrimaryKeyFactory " + e.getMessage());
}
}}
and my realm config class
public abstract class RealmBaseApplication extends Application {
private RealmConfiguration realmConfiguration;
protected RealmConfiguration getRealmConfig() {
if (realmConfiguration == null) {
realmConfiguration = new RealmConfiguration
.Builder()
.deleteRealmIfMigrationNeeded()
.build();
}
Realm.setDefaultConfiguration(realmConfiguration);
return realmConfiguration;
}
protected void resetRealm() {
Realm.deleteRealm(getRealmConfig());
}}
kind regards
viktoria
ok fixed by myself. had add butterknife tonight. and with that i add apt to my build.gradle... i removed
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
apply plugin: 'com.neenbedankt.android-apt'
and replaced
apt 'com.jakewharton:butterknife-compiler:8.5.1'
with
annotationProcessor 'com.jakewharton:butterknife-compiler:8.5.1'

Huge ms access database with javafx, ucanaccess

I have a huge MS Access database file (aprrox. 1gb) and about 5 different GUI (FXML). Each fxml contains data from different tables. I am using ucanaccess to connect with database. Now I am having problem in connecting with database. I never get connection. It works fine with smaller database file. I am using service and task for background thread. Could someone tell me what can be the best approach to overcome this problem.
private Service backgroundService;
private Connection ucaConn;
#FXML
private void handleButtonAction(ActionEvent event) {
backgroundService = new Service() {
#Override
protected Task createTask() {
return new Task() {
#Override
protected Object call() throws Exception {
try {
ucaConn = getUcanaccessConnection(DataCarrier.getInstance().getDatabaseLocation());
} catch (SQLException | IOException ex) {
Logger.getLogger(HomeController.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
};
}
};
backgroundService.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
#Override
public void handle(WorkerStateEvent event) {
System.out.println("Done");
errorMessage.textProperty().unbind();
String timeStamp = new SimpleDateFormat("mm:ss").format(Calendar.getInstance().getTime());
System.out.println("End time: " + timeStamp);
}
});
errorMessage.textProperty().bind(backgroundService.messageProperty());
backgroundService.restart();
}
}
}
private static Connection getUcanaccessConnection(String pathNewDB) throws SQLException,
IOException {
String url = UcanaccessDriver.URL_PREFIX + pathNewDB + ";newDatabaseVersion=V2003";
return DriverManager.getConnection(url, "sa", "");
}

SpringBoot Undertow : how to dispatch to worker thread

i'm currently have a look a springboot undertow and it's not really clear (for me) how to dispatch an incoming http request to a worker thread for blocking operation handling.
Looking at the class UndertowEmbeddedServletContainer.class, it look like there is no way to have this behaviour since the only HttpHandler is a ServletHandler, that allow #Controller configurations
private Undertow createUndertowServer() {
try {
HttpHandler servletHandler = this.manager.start();
this.builder.setHandler(getContextHandler(servletHandler));
return this.builder.build();
}
catch (ServletException ex) {
throw new EmbeddedServletContainerException(
"Unable to start embdedded Undertow", ex);
}
}
private HttpHandler getContextHandler(HttpHandler servletHandler) {
if (StringUtils.isEmpty(this.contextPath)) {
return servletHandler;
}
return Handlers.path().addPrefixPath(this.contextPath, servletHandler);
}
By default, in undertow all requests are handled by IO-Thread for non blocking operations.
Does this mean that every #Controller executions will be processed by a non blocking thread ? or is there a solution to chose from IO-THREAD or WORKER-THREAD ?
I try to write a workaround, but this code is pretty uggly, and maybe someone has a better solution:
BlockingHandler.class
#Target({ElementType.TYPE})
#Retention(RetentionPolicy.RUNTIME)
#Documented
public #interface BlockingHandler {
String contextPath() default "/";
}
UndertowInitializer.class
public class UndertowInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
#Override
public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
configurableApplicationContext.addBeanFactoryPostProcessor(new UndertowHandlerPostProcessor());
}
}
UndertowHandlerPostProcessor.class
public class UndertowHandlerPostProcessor implements BeanDefinitionRegistryPostProcessor {
#Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
scanner.addIncludeFilter(new AnnotationTypeFilter(BlockingHandler.class));
for (BeanDefinition beanDefinition : scanner.findCandidateComponents("org.me.lah")){
try{
Class clazz = Class.forName(beanDefinition.getBeanClassName());
beanDefinitionRegistry.registerBeanDefinition(clazz.getSimpleName(), beanDefinition);
} catch (ClassNotFoundException e) {
throw new BeanCreationException(format("Unable to create bean %s", beanDefinition.getBeanClassName()), e);
}
}
}
#Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
//no need to post process defined bean
}
}
override UndertowEmbeddedServletContainerFactory.class
public class UndertowEmbeddedServletContainerFactory extends AbstractEmbeddedServletContainerFactory implements ResourceLoaderAware, ApplicationContextAware {
private ApplicationContext applicationContext;
#Override
public EmbeddedServletContainer getEmbeddedServletContainer(ServletContextInitializer... initializers) {
DeploymentManager manager = createDeploymentManager(initializers);
int port = getPort();
if (port == 0) {
port = SocketUtils.findAvailableTcpPort(40000);
}
Undertow.Builder builder = createBuilder(port);
Map<String, Object> handlers = applicationContext.getBeansWithAnnotation(BlockingHandler.class);
return new UndertowEmbeddedServletContainer(builder, manager, getContextPath(),
port, port >= 0, handlers);
}
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
...
override UndertowEmbeddedServletContainer.class
public UndertowEmbeddedServletContainer(Builder builder, DeploymentManager manager,
String contextPath, int port, boolean autoStart, Map<String, Object> handlers) {
this.builder = builder;
this.manager = manager;
this.contextPath = contextPath;
this.port = port;
this.autoStart = autoStart;
this.handlers = handlers;
}
private Undertow createUndertowServer() {
try {
HttpHandler servletHandler = this.manager.start();
String path = this.contextPath.isEmpty() ? "/" : this.contextPath;
PathHandler pathHandler = Handlers.path().addPrefixPath(path, servletHandler);
for(Entry<String, Object> entry : handlers.entrySet()){
Annotation annotation = entry.getValue().getClass().getDeclaredAnnotation(BlockingHandler.class);
System.out.println(((BlockingHandler) annotation).contextPath());
pathHandler.addPrefixPath(((BlockingHandler) annotation).contextPath(), (HttpHandler) entry.getValue());
}
this.builder.setHandler(pathHandler);
return this.builder.build();
}
catch (ServletException ex) {
throw new EmbeddedServletContainerException(
"Unable to start embdedded Undertow", ex);
}
}
set initializer to the application context
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).initializers(new UndertowInitializer()).run(args);
}
finaly create a HttpHandler that dispatch to worker thread
#BlockingHandler(contextPath = "/blocking/test")
public class DatabaseHandler implements HttpHandler {
#Autowired
private EchoService echoService;
#Override
public void handleRequest(HttpServerExchange httpServerExchange) throws Exception {
if(httpServerExchange.isInIoThread()){
httpServerExchange.dispatch();
}
echoService.getMessage("my message");
}
}
As you can see, my "solution" is really heavy, and i would really appreciate any help to simplify it a lot.
Thank you
You don't need to do anything.
Spring Boot's default Undertow configuration uses Undertow's ServletInitialHandler in front of Spring MVC's DispatcherServlet. This handler performs the exchange.isInIoThread() check and calls dispatch() if necessary.
If you place a breakpoint in your #Controller, you'll see that it's called on a thread named XNIO-1 task-n which is a worker thread (the IO threads are named XNIO-1 I/O-n).

Resources