Play-slick - Is default.db required? - database

I'm working on an application using Play and Slick. This app requires access to (at least) two databases and this is working fine when one is defined as default and other is named. Eg.,
db.default.driver = "com.mysql.jdbc.Driver"
db.default.url = "jdbc:mysql://localhost:3306/db1"
db.db2.driver = "com.mysql.jdbc.Driver"
db.db2.url = "jdbc:mysql://localhost:3306/db2"
I can then happily access each db as follows
DB.withSession { implicit session => ??? }
DB("db2").withSession { implicit session => ??? }
However, this doesn't really make sense as there is no reason DB1 should be the default. The DBs contain different types of data, neither is the default, both are important. What I would like is:
db.db1.driver = "com.mysql.jdbc.Driver"
db.db1.url = "jdbc:mysql://localhost:3306/db1"
db.db2.driver = "com.mysql.jdbc.Driver"
db.db2.url = "jdbc:mysql://localhost:3306/db2"
Play-scala barfs at this thought. It needs a default db driver and URL and it needs to be able to connect to it.
Anyone know anyway to change this behaviour or to trick play into thinking it has a default?
UPDATE
To be clear, I've greped my code to ensure that I'm not using DB.withSession anywhere. That is, every time I create a session I use DB("db1").withSession or DB("db2").withSession. However, when I run my test, I still get an exception:
Caused by: Configuration error: Configuration error[Slick error : jdbc driver not defined in application.conf for db.default.driver key]
Something somewhere is trying to load the default config.

Default is just a name, with some convenience functions (withSession and withTransaction without name), so, no you do not need to have a default connection if it does not fit your project.

Related

What is the proper way to test SpringBoot Database with H2?

I am trying to run Springboot test with H2 in-memory db with Mybatis.
So far I have done
configuring h2 DB in application-test.properties
adding annotation
#SpringBootTest, #TestPropertySource (locations = "TEST_APPLICATION_PROPERTIES_LOCATION")
autowiring dao and serviceImpl beans
adding seed.sql and purge.sql to the test class with
#SqlGroup({
#Sql(executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, scripts = "classpath:/database/seed.sql"),
#Sql(executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, scripts = "classpath:/database/purge.sql") })
Despite the above measures, I still have two problems
I can't retrieve user that I input with the seed.sql. I made a user with id="admin", pw="admin", and was trying to retrieve with findById("admin"). But it always returns null.
I can't open h2 DB while debugging with the #test. I simply can't access h2 with localhost:8080/h2-console (the path was written explicitly in application-test.properties)
Is there any extra measure that I should take to test SpringBoot with h2?
Add spring.h2.console.enabled=true in your properties file.

How do I use another database other than default in play-framework?

Up until I was using only one database in my application. So for any sql query, I was just using the default database. Below is given the info about the database.
db.default.driver=org.postgresql.Driver
db.default.url="postgres://user:password#localhost:5439/database_name"
These info are saved in the appliction.conf file. In the code below DB is the default database.
DB.withConnection {
conn =>
{
val statement = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)
try {
statement.execute(sql)
}
catch {
case e: Exception => Logger.debug("There is some error with the database")
}
}
}
But I need to use another database. Below is given the info about the database.
db.um.driver=com.mysql.jdbc.Driver
db.um.url="mysql://user:password#localhost:3306/database_name"
These info are also saved in the application.conf file. Now how do I access that database and run an sql command.
The data source called default, as the name suggests, is used as a default value for all connections. You can see that the withConnection() method takes a parameter with a data source name but if nothing is passed, "default" is used instead.
To use your additional data source you have to specify it as a parameter of the withConnection() method.
DB.withConnection("um") { conn =>
// implement your action
}
In case someone is like myself, is looking to use multiple data resources in Play 2.6: This is not the answer.
We need to define the name of the database when we inject the instance of the Database, using #NamedDatabase:
class Customer #Inject()(#NamedDatabase("customer") db: Database){ ??? }

CakePHP ini_set on Shared Host

I'm on a shared host and ini_set function is disabled for security reasons. I'm trying to deploy CakePHP 2.4.1 on this host. Fresh cake installation results in a blank page, with no errors shown, instead if I comment these lines:
\lib\Cake\Model\Datasource\CakeSession.php
if (empty($_SESSION)) {
if (!empty($sessionConfig['ini']) && is_array($sessionConfig['ini'])) {
foreach ($sessionConfig['ini'] as $setting => $value) {
if (ini_set($setting, $value) === false) {
throw new CakeSessionException(__d('cake_dev', 'Unable to configure the session, setting %s failed.', $setting));
}
}
}
}
Everything seems to works fine. Now, I'm asking what is the downside of keeping that snippets commented (in other word, what is that code responsible for)?
As the exception message, the method name and the rest of the code indicates, it configures the session settings, session name, cookie lifetime, save handler, etc...
Your code may run fine, and you should be able to use the PHP session_*() functions instead to configure the settings (the best place for that would probably your bootstrap.php). Also writing a dummy value into $_SESSION seems to prevent the CakeSession::_configureSession() to use ini_set(), so you don't have to modify it.
So this might work, but it shouldn't be necessary to jump through such hoops. There's no need to disable ini_set() in a properly set up shared hosting environment, and personally I'd change the hoster in case they are unable to change this behaviour.

App Engine Instance ID

Is it possible to get info on what instance you're running on? I want to output just a simple identifier for which instance the code is currently running on for logging purposes.
Since there is no language tag, and seeing your profile history, I assume you are using GAE/J?
In that case, the instance ID information is embedded in one of the environment attributes that you could get via ApiProxy.getCurrentEnvironment() method. You could then extract the instance id from the resulting map using key BackendService.INSTANCE_ID_ENV_ATTRIBUTE.
Even though the key is stored in BackendService, this approach will also work for frontend instances. So in summary, the following code would fetch the instance ID for you:
String tInstanceId = ApiProxy.getCurrentEnvironment()
.getAttributes()
.get( BackendService.INSTANCE_ID_ENV_ATTRIBUTE )
.toString();
Please keep in mind that this approach is quite undocumented by Google, and might subject to change without warning in the future. But since your use case is only for logging, I think it would be sufficient for now.
With the advent of Modules, you can get the current instance id in a more elegant way:
ModulesServiceFactory.getModulesService().getCurrentInstanceId()
Even better, you should wrap the call in a try catch so that it will work correctly locally too.
Import this
import com.google.appengine.api.modules.ModulesException;
import com.google.appengine.api.modules.ModulesServiceFactory;
Then your method can run this
String instanceId = "unknown";
try{
instanceId = ModulesServiceFactory.getModulesService().getCurrentInstanceId();
} catch (ModulesException e){
instanceId = e.getMessage();
}
Without the try catch, you will get some nasty errors when running locally.
I have found this super useful for debugging when using endpoints mixed with pub-sub and other bits to try to determine why some things work differently and to determine if it is related to new instances.
Not sure about before, but today in 2021 the system environment variable GAE_INSTANCE appears to contain the instance id:
instanceId = System.getenv("GAE_INSTANCE")

require.js i18n module - how to load a language from server?

My app setup is require js with backbone js.
I've got a situation where I'd like to be able to get the appropriate language for an unknown user from browser navigator object, but where i could also load the preferred language for a known user from the server if this information exists.
is there a way to accomplish this? the only access point i could find is in require.config, but normally this is being loaded before any data arrives from the server.
thanks in advance!
Is there any default language you have set to a user?
First on log-in bring user information from server
you may use this kind of code
setLanguage: function(languageCode){
enter code here
this.set("languageCode",languageCode);
if(this.isAvailable(i18n)){`enter code here`
i18n.userSelected(languageCode);
}else{`enter code here`
this.showErrorMsg(window.i18n.msgStore['default_language_is_set_to'] + " " + constants.language[languageCode]);
}
},
set:function(key, value){
localStorage.setItem(key, value);`enter code here`
},
Here the language is also set into the local storage so that later on you can access it

Resources