I am studying the tutorial javarevoltions JSF 2 + PrimeFaces 5 + 4 + Spring Hibernate 4.
Essse tutorial is based on weblogic server and Oracle database.
My problem is I want to use glassfish with MySQL instead.
There is a file called utilidades.java containing webologic properties.
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
public class Utilities {
public static Object getEJBRemote (nameEJB String, String iface) throws Exception {
Context context;
Properties props = new Properties ();
props.put (Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
props.put (Context.PROVIDER_URL, "http: // localhost: 7001");
try {
context = new InitialContext (props);
String lookup nameEJB + = "#" + iface;
System.out.println ("Lookup" + lookup);
return context.lookup (lookup);
} Catch (Exception ex) {
throw new Exception ("There is EJB: '" + nameEJB + "'.");
}
}
}
I've changed to:
props.put (Context.INITIAL_CONTEXT_FACTORY, "org.springframework.jndi.JndiObjectFactoryBean");
props.put (Context.PROVIDER_URL, "http: // localhost: 4848");
This I saw a tutorial on the Internet, using glassfish and mysql. I created the ping successfully datasource in glassfish.
When I do a debbug it appears:
ex = (javax.naming.NoInitialContextException)
javax.naming.NoInitialContextException: Can not instantiate class:
org.springframework.jndi.JndiObjectFactoryBean [Root exception is
java.lang.ClassCastException:
org.springframework.jndi.JndiObjectFactoryBean can not be cast to
javax.naming .spi.InitialContextFactory]
What am I doing wrong?
Your problem is that weblogic.jndi.WLInitialContextFactory is not an InitialContextFactory. I think the value you want for Glassfish is com.sun.enterprise.naming.SerialInitContextFactory:
Properties props = new Properties ();
props.put (Context.INITIAL_CONTEXT_FACTORY, "com.sun.enterprise.naming.SerialInitContextFactory");
props.put (Context.PROVIDER_URL, "http: // localhost: 7001");
This answer has more detail.
Related
I have an application where I am trying to distribute reads & writes between two replicas. For some reason JPA is only using my read-replica, not the write replica. The write replica is the primary replica. The result is that when I use JPA to try and write data I get and 'UPDATE command denied' error because it is using the read only datasource. I have tried doing my own annotation and using the #Transactional annotation. Both annotations are called via AOP with the correct datasource but JPA will not use it.
FYI Spring JDBC works correctly via the custom annotation. This is strictly a JPA issue. Below is some code:
My AOP class:
#Aspect
#Order(20)
#Component
public class RouteDataSourceInterceptor {
#Around("#annotation(com.kenect.db.common.annotations.UseDataSource) && execution(* *(..))")
public Object proceed(ProceedingJoinPoint pjp) throws Throwable {
try {
MethodSignature signature = (MethodSignature) pjp.getSignature();
Method method = signature.getMethod();
UseDataSource annotation = method.getAnnotation(UseDataSource.class);
RoutingDataSource.setDataSourceName(annotation.value());
return pjp.proceed();
} finally {
RoutingDataSource.resetDataSource();
}
}
#Around("#annotation(transactional)")
public Object proceed(ProceedingJoinPoint proceedingJoinPoint, Transactional transactional) throws Throwable {
try {
if (transactional.readOnly()) {
RoutingDataSource.setDataSourceName(SQL_READ_REPLICA);
Klogger.info("Routing database call to the read replica");
} else {
RoutingDataSource.setDataSourceName(SQL_MASTER_REPLICA);
Klogger.info("Routing database call to the primary replica");
}
return proceedingJoinPoint.proceed();
} finally {
RoutingDataSource.resetDataSource();
}
}
}
My RoutingDataSource class:
public class RoutingDataSource extends AbstractRoutingDataSource {
private static final ThreadLocal<String> currentDataSourceName = new ThreadLocal<>();
public static synchronized void setDataSourceName(String name) {
currentDataSourceName.set(name);
}
public static synchronized void resetDataSource() {
currentDataSourceName.remove();
}
#Override
protected Object determineCurrentLookupKey() {
return currentDataSourceName.get();
}
}
AbstractDynamicDataSourceConfig
public abstract class AbstractDynamicDataSourceConfig {
private final ConfigurableEnvironment environment;
public AbstractDynamicDataSourceConfig(ConfigurableEnvironment environment) {
this.environment = environment;
}
protected DataSource getRoutingDataSource() {
Map<String, String> props = DBConfigurationUtils.getAllPropertiesStartingWith("spring.datasource", environment);
List<String> dataSourceNames = DBConfigurationUtils.getDataSourceNames(props.keySet());
RoutingDataSource routingDataSource = new RoutingDataSource();
Map<Object, Object> dataSources = new HashMap<>();
DataSource masterDataSource = null;
for (String name : dataSourceNames) {
DataSource dataSource = getDataSource("spring.datasource." + name);
dataSources.put(name, dataSource);
if (masterDataSource == null && name.toLowerCase().contains("master")) {
masterDataSource = dataSource;
}
}
if (dataSources.isEmpty()) {
throw new KenectInvalidParameterException("No datasources found.");
}
routingDataSource.setTargetDataSources(dataSources);
if (masterDataSource == null) {
masterDataSource = (DataSource) dataSources.get(dataSourceNames.get(0));
}
routingDataSource.setDefaultTargetDataSource(masterDataSource);
return routingDataSource;
}
protected DataSource getDataSource(String prefix) {
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setJdbcUrl(environment.getProperty(prefix + ".jdbcUrl"));
hikariConfig.setUsername(environment.getProperty(prefix + ".username"));
hikariConfig.setPassword(environment.getProperty(prefix + ".password"));
return new HikariDataSource(hikariConfig);
}
}
application.yaml
spring:
datasource:
master:
jdbcUrl: jdbc:mysql://my-main-replica
username: some-user
password: some-password
read-replica:
jdbcUrl: jdbc:mysql://my-read-replica
username: another-user
password: another-password
If I use the annotation on with JDBC template then it works as expected:
THIS WORKS:
// Uses main replica as it is not specified
public Message insertMessage(Message message) {
String sql = "INSERT INTO message(" +
" `conversationId`," +
" `body`)" +
" VALUE (" +
" :conversationId," +
" :body" +
")";
MapSqlParameterSource parameters = new MapSqlParameterSource();
parameters.addValue("conversationId", message.getConversationId());
parameters.addValue("body", message.getBody());
namedJdbcTemplate.update(sql, parameters);
}
// Uses read replica
#UseDataSource(SQL_READ_REPLICA)
public List<Message> getMessage(long id) {
MapSqlParameterSource parameters = new MapSqlParameterSource();
parameters.addValue("id", id);
String sql = "SELECT " +
" conversationId," +
" body" +
" FROM message"
" WHERE id = :id";
return namedJdbcTemplate.query(sql, parameters, new BeanPropertyRowMapper<>(Message.class));
}
If I use a JPA interface it always uses the read replica:
THIS FAILS:
#Repository
public interface MessageJpaRepository extends JpaRepository<MessageEntity, Long> {
// Should use the main-replica but always uses the read-replica
#Modifying
#Query(value =
"UPDATE clarioMessage SET" +
" body = :body" +
" WHERE id = :id" +
" AND organizationId = :organizationId",
nativeQuery = true)
#Transactional
int updateMessageBodyByIdAndOrganizationId(#Param("body") String body, #Param("id")long id, #Param("organizationId")long organizationId);
}
So I am just getting the error below when I try to use the main-replica. I have tried using the #UseDataSource annotation and AOP does actually intercept it. But, it still uses the read-replica.
java.sql.SQLSyntaxErrorException: UPDATE command denied to user 'read-replica-user'#'read replica IP' for table 'message'
What am I missing?
When you use #UseDataSource, it is working so it seems rules out any issues with implementation of aspect.
And When you #Transactional, it uses the secondary replica, regardless of your your AOP being invoked. My suspicion is by the TransactionInterceptor created by spring is invoked before your RouteDataSourceInterceptor. You can try the following:
Put a breakpoint in your aop method as well as a break point in org.springframework.transaction.interceptor.TransactionInterceptor.invoke method to see which one invokes first. You want your interceptor invoked first
If your interceptor is not invoked first, I would modify your interceptor to have high order as follows.
#Aspect
#Order(Ordered.HIGHEST_PRECEDENCE)
#Component
public class RouteDataSourceInterceptor {
I still don't understand how you are telling TransactionInterceptor to choose the DataSource you set in RouteDataSourceInterceptor. I have not used multi tenant setup but recently I came across a question which I helped to solve and I can see it is implementing AbstractDataSourceBasedMultiTenantConnectionProviderImpl. So I hope you have something similar. Not able to switch database after defining Spring AOP
I am building an workflow for Corda. I want to use the Hikari connection pool library for connecting to MySql database. I AM NOT trying to replace the, ledger H2 database. This database is for storing/retrieving some information, which is not needed in the ledger. I am able to connect to MySql WITHOUT Hikari. However when I use Hikari, I get an error.
java.lang.ClassNotFoundException: com.mysql.cj.jdbc.MysqlConnectionPoolDataSource
I have tested the Hikari code, as a standalone jar file. It works fine. It is a combination of the way corda loads and runs the jar files, inside cordapps directory, which is causing the issue. Since the class is part of the jar. This seems it a little off
I have added the MySql dependency, inline with what is mentioned in https://docs.corda.net/cordapp-build-systems.html#setting-your-dependencies
I am also able to connect to the MySql DB, if I am not using Hikari.
I explored the cordapp jar .
And I could see that the requisite jar is present inside the cordapp jar.
Gradle dependencies for the cordapp
dependencies {
testCompile "junit:junit:$junit_version"
// Corda dependencies.
cordaCompile "$corda_release_group:corda-core:$corda_release_version"
cordaRuntime "$corda_release_group:corda:$corda_release_version"
testCompile "$corda_release_group:corda-node-driver:$corda_release_version"
runtime "mysql:mysql-connector-java:8.0.11"
cordaCompile "com.zaxxer:HikariCP:2.5.1"
// CorDapp dependencies.
cordapp project(":contracts")
}
Sample code
public class DataSource {
private static final Logger logger = LoggerFactory.getLogger(DataSource.class);
private static HikariConfig config = new HikariConfig();
private static HikariDataSource ds;
static {
try {
logger.info("Connecting with connection pool datasource");
config.setDataSourceClassName("com.mysql.cj.jdbc.MysqlConnectionPoolDataSource");
config.addDataSourceProperty("useSSL", "false");
config.addDataSourceProperty("user", "username");
config.addDataSourceProperty("password", "password");
config.addDataSourceProperty("serverName", "localhost");
config.addDataSourceProperty("useSSL", "false");
config.addDataSourceProperty("port",Integer.parseInt("3306"));
config.addDataSourceProperty("cachePrepStmts", "true");
config.addDataSourceProperty("prepStmtCacheSize", "250");
config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
config.addDataSourceProperty("requireSSL", "false");
config.addDataSourceProperty("serverTimezone", "UTC");
config.addDataSourceProperty("useServerPrepStmts", "true");
config.addDataSourceProperty("allowPublicKeyRetrieval", "true");
config.addDataSourceProperty("databaseName", "database");
config.setPoolName("Hikari-MySql Pool Name");
logger.error("-- Create Hikari Datasource with config {} --", config);
ds = new HikariDataSource(config);
} catch (Throwable t) {
logger.error("Error Occurred during Datasource Initializaiton", t);
throw t;
}
}
private DataSource() {
}
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
}
public class MySqlConnection {
static private final Logger logger = LoggerFactory.getLogger(MySqlConnection.class);
public Connection getMySqlConnection() {
Connection conn = null;
try {
conn = DataSource.getConnection();
logger.info("------------> Got conne :: " + conn);
} catch (SQLException e) {
logger.error("SQLException :: " + e);
}
return conn;
}
}
public class DataSourceTest {
static private final Logger logger = LoggerFactory.getLogger(DataSourceTest.class);
public static void main(String[] args) {
MySqlConnection mySqlConnection = new MySqlConnection();
Connection conn = null;
try {
conn = mySqlConnection.getMySqlConnection();
logger.info("------------> Got connection :: " + conn);
Statement statement = conn.createStatement();
ResultSet rs = statement.executeQuery("{some select statement}");
} catch (SQLException e) {
logger.error("SQLException :: " + e);
}
}
}
Exception:
Caused by: java.lang.RuntimeException: java.lang.ClassNotFoundException: com.mysql.cj.jdbc.MysqlConnectionPoolDataSource
at com.zaxxer.hikari.util.UtilityElf.createInstance(UtilityElf.java:90) ~[HikariCP-2.5.1.jar:?]
at com.zaxxer.hikari.pool.PoolBase.initializeDataSource(PoolBase.java:314) ~[HikariCP-2.5.1.jar:?]
at com.zaxxer.hikari.pool.PoolBase.<init>(PoolBase.java:108) ~[HikariCP-2.5.1.jar:?]
at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:99) ~[HikariCP-2.5.1.jar:?]
at com.zaxxer.hikari.HikariDataSource.<init>(HikariDataSource.java:71) ~[HikariCP-2.5.1.jar:?]
If I run the code from a main class inside a jar, it works. But it does not work from inside a cordapp
In MySQL for HikariCP use setJdbcUrl instead of setDataSourceClassName
config.setJdbcUrl("jdbc:mysql://localhost:3306/simpsons");
The MySQL DataSource is known to be broken with respect to network timeout support. Use jdbcUrl configuration instead.
Check your dependency tree. I think you have some collision with "mysql-connector-java" dependency, which cause mess in class loader.
I am trying to add documents to couchbase server(admin UI) and then trying to retrieve it using couchbase Lite via sync gateway but unable to do so. What I am trying to achieve is I already have a lot of data in couchbase server now I want my mobile app to use it and because that data was not added using sync gateway I want to achieve something like I added data using web now I want my couchbase lite to connect to that couchbase server and retrieve data. Is there any way to do it? or only data that has been added using sync gateway can be retrieved?
EDIT 1 Added Source Codes
Below is the android app code
package com.couchbase.examples.couchbaseevents;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import com.couchbase.lite.CouchbaseLiteException;
import com.couchbase.lite.Database;
import com.couchbase.lite.Document;
import com.couchbase.lite.Manager;
import com.couchbase.lite.android.AndroidContext;
import com.couchbase.lite.replicator.Replication;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
public class MainActivity extends AppCompatActivity {
public static final String DB_NAME = "couchbaseevents";
final String TAG = "CouchbaseEvents";
Database database = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, "Begin Couchbase Events App");
Manager manager = null;
try {
manager = new Manager(new AndroidContext(this), Manager.DEFAULT_OPTIONS);
database = manager.getDatabase(DB_NAME);
} catch (Exception e) {
Log.d(TAG, "Error getting database", e);
return;
}
/*try {
database.delete();
} catch (Exception e) {
Log.e(TAG, "Cannot delete database", e);
return;
}*/
try {
startReplications();
} catch (CouchbaseLiteException e) {
e.printStackTrace();
}
Document retrievedDocument = database.getDocument("123");
// display the retrieved document
Log.d(TAG, "retrievedDocument=" + String.valueOf(retrievedDocument.getProperties()));
Log.d(TAG, "End Couchbase Events App");
}
private URL createSyncURL(boolean isEncrypted){
URL syncURL = null;
String host = "http://172.16.25.100";
String port = "4986";
String dbName = "sync_gateway";
try {
//syncURL = new URL("http://127.0.0.1 :4986/sync_gateway");
syncURL = new URL(host + ":" + port + "/" + dbName);
} catch (Exception me) {
me.printStackTrace();
}
Log.d(syncURL.toString(),"URL");
return syncURL;
}
private void startReplications() throws CouchbaseLiteException {
Replication pull = database.createPullReplication(this.createSyncURL(false));
Replication push = database.createPushReplication(this.createSyncURL(false));
pull.setContinuous(true);
push.setContinuous(true);
pull.start();
push.start();
if(!push.isRunning()){
Log.d(TAG, "MyBad");
}
/*if(!push.isRunning()) {
Log.d(TAG, "Replication is not running due to " +push.getLastError().getMessage());
Log.d(TAG, "Replication is not running due to " +push.getLastError().getCause());
Log.d(TAG, "Replication is not running due to " +push.getLastError().getStackTrace());
Log.d(TAG, "Replication is not running due to " +push.getLastError().toString());
}*/
}
}
"123" is the document id of document I created in CouchBase server using admin UI
As you can see I first deleted the database( commented part) to make sure there is no document in database and then ran the above replication code.
Below is the sync gateway config file
{
"log":["CRUD+", "REST+", "Changes+", "Attach+"],
"interface":":4986",
"adminInterface":":14985",
"databases": {
"sync_gateway": {
"server":"http://172.16.25.100:8091",
"bucket":"sync_gateway",
"sync":`
function (doc) {
channel (doc.channels);
}`,
"users": {
"GUEST": {
"disabled": false,
"admin_channels": ["*"]
}
}
}
}
}
I also want to ask is there any UI or command line to access CBL. I am currently using CBL in android studio so I dont know how to access its UI or command line
Just for the information, I am able to push data from CBL to CouchBase server
We can solve the above issue by shadowing. If I want to sync my data from the already made bucket to sync gateway bucket shadowing is required. More about Shadowing here
I'm trying to connect from a Google Endpoints server to a Google Cloud SQL server. I'm modifying the Greetings.getGreeting() method in this tutorial:
https://cloud.google.com/appengine/docs/java/endpoints/getstarted/backend/helloendpoints
to call the Cloud mysql database as demonstrated in this tutorial (see doGet method):
https://cloud.google.com/appengine/docs/java/cloud-sql/#enable_connector_j
I have made sure that I can connect to the database from my machine mysql client. The database instance "simple" has a single table "simpletable" who's rows hold an entityID and a string. (But I'm not able to connect, so that's not too important yet.)
This is my endpoints code:
package com.example.helloendpoints;
import com.google.api.server.spi.config.Api;
import com.google.api.server.spi.config.ApiMethod;
import com.google.api.server.spi.response.NotFoundException;
import com.google.appengine.api.users.User;
import java.sql.*;
import java.util.ArrayList;
import javax.inject.Named;
/**
* Defines v1 of a helloworld API, which provides simple "greeting" methods.
*/
#Api(
name = "helloworld",
version = "v1",
scopes = {Constants.EMAIL_SCOPE},
clientIds = {Constants.WEB_CLIENT_ID,
Constants.ANDROID_CLIENT_ID,
Constants.IOS_CLIENT_ID,
Constants.API_EXPLORER_CLIENT_ID},
audiences = {Constants.ANDROID_AUDIENCE}
)
public class Greetings {
public static ArrayList<HelloGreeting> greetings = new ArrayList<HelloGreeting>();
static {
greetings.add(new HelloGreeting("hello world!"));
greetings.add(new HelloGreeting("goodbye world!"));
}
public HelloGreeting getGreeting(#Named("id") Integer id) throws NotFoundException {
// pair to use when running local endpoint server
String urlFromDev = "jdbc:mysql://173.194.XXX.90:3306/simple?user=root";
String classForNameFromDev = "com.mysql.jdbc.Driver";
// pair to use when running cloud endpoint server
String classForNameFromCloud = "com.mysql.jdbc.GoogleDriver";
String urlFromCloud = "jdbc:google:mysql://"
+ Constants.PROJECT_ID + ":"
+ Constants.CLOUD_SQL_INSTANCE_NAME +"/"
+ Constants.DATABASE_NAME + "?user=root";
HelloGreeting helloGreeting = new HelloGreeting();
try {
Class.forName(classForNameFromDev);
// Class.forName(classForNameFromCloud);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
Connection connection = DriverManager.getConnection(urlFromDev);
// Connection connection = DriverManager.getConnection(urlFromCloud);
try {
String statement = "Select simplestring from simpletable where entryID = ?";
PreparedStatement preparedStatement = connection.prepareStatement(statement);
preparedStatement.setInt(1, id);
ResultSet resultSet = preparedStatement.executeQuery();
if (!resultSet.wasNull()) {
helloGreeting.setMessage(resultSet.getString("simplestring"));
} else {
throw new NotFoundException("Greeting not found with an index: " + id);
}
} finally {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
return helloGreeting;
}
#ApiMethod(name = "greetings.multiply", httpMethod = "post")
public HelloGreeting insertGreeting(#Named("times") Integer times, HelloGreeting greeting) {
HelloGreeting response = new HelloGreeting();
StringBuilder responseBuilder = new StringBuilder();
for (int i = 0; i < times; i++) {
responseBuilder.append(greeting.getMessage());
}
response.setMessage(responseBuilder.toString());
return response;
}
#ApiMethod(name = "greetings.authed", path = "hellogreeting/authed")
public HelloGreeting authedGreeting(User user) {
HelloGreeting response = new HelloGreeting("hello " + user.getEmail());
return response;
}
}
I have tried to enable mysql connector/j in my appengine-web.xml
<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<use-google-connector-j>true</use-google-connector-j>
<application>backendapitutorial-1XXX</application>
<version>${app.version}</version>
<threadsafe>true</threadsafe>
<system-properties>
<property name="java.util.logging.config.file" value="WEB- INF/logging.properties"/>
</system-properties>
</appengine-web-app>
Whichever way I build+depl0y it (Dev or cloud), I always get
java.sql.SQLException: No suitable driver found for jdbc:mysql://173.194.XXX.90:3306/simple?user=root
or
java.sql.SQLException: No suitable driver found for jdbc:google:mysql://backendapitutorial-XXXX:simple/simple?user=root
(I replaced the real IP and project name with "X"s for this post).
I've already looked at these:
java.sql.SQLException: No suitable driver found for jdbc:mysql://localhost:3306/dbname
ClassNotFoundException: com.mysql.jdbc.GoogleDriver
What does 'Class.forName("org.sqlite.JDBC");' do?
I'm building with Maven and working on IntelliJ IDE.
Any help is greatly appreciated. Thanks.
First of all thanks to everyone that answers questions on here. I have used this forum as a java bible. This is a homework problem and here is the assignment:
Write a program in Java that uses sockets to connect to a web server on port 80, requests a web page using GET of the HTTP protocol, and displays the resulting HTML
Not sure if I am doing this right or not. I have a very limited understanding of java. Most of this is from tutorials I have been going through. Any website links would be greatly appreciated.
Here is my error message:
Exception in thread "main" java.lang.Error: Unresolved compilation problems:
Type mismatch: cannot convert from java.net.Socket to Socket
The method getInputStream() is undefined for the type Socket
Here is my code:
import java.io.*;
import java.net.*;
public class Server
{
public static void main(String[] args) throws Exception
{
Server SERVER = new Server();
SERVER.run();
}
public void run() throws Exception
{
ServerSocket one = new ServerSocket(80);
//these are the two lines of code it is warning about
Socket myskt = one.accept();
InputStreamReader IR = new InputStreamReader(myskt.getInputStream());
//end of warnings
BufferedReader BR = new BufferedReader(IR);
String message = BR.readLine();
System.out.println(message);
if (message != null)
{
PrintStream PS = new PrintStream(System.out);
PS.println("Message Received");
}
URL website = new URL("www.dogs.com");
URLConnection yc = website.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(
yc.getInputStream()));
String inputLine;
while ((inputLine = in .readLine()) != null)
System.out.println(inputLine);
one.close();
}
// TODO Auto-generated method stub
}
The issue is that our code is not well-formed - you have a compilation error. My guess is that you have a class Socket in the same package as the class you're compiling, or a left-over class file (Socket.class) on the classpath. When the compiler runs, it uses the package local version of Socket, which is not the same type as java.net.Socket - hence the exception.
To resolve thisuse the fully qualified name java.net.Socket when declaring myskt