i need access to several databases per environment.
Until now i've only seen examples with exactly one database connection config per environment in database.properties.
Is it possible to have several connection configs in there for an environment and let ActiveJdbc handle opening the correct one when using DB.open("first") or do i need to load these configs by myself in that case?
You can have named connections and bind them to your thread:
new DB("corporation").open("com.mysql.jdbc.Driver", "jdbc:mysql://localhost/test", "root", "p#ssw0rd");
new DB("university").open("oracle.jdbc.driver.OracleDriver", "jdbc:oracle:thin:#localhost:1521:xe", "activejdbc", "activejdbc");
After that, you can declare models to associate with named connections:
#DbName("corporation")
public class Employee extends Model {}
...
#DbName("university")
public class Student extends Model {}
For more, see the doc for your case:
http://javalite.io/database_connection_management#multiple-database-example
Related
I have a big architecture question about how to pass set of configurable / replaceable objects to modules of my project?
For example the set may be a bot, logger, database, etc.
Currently I'm just importing they, it make a big problem when you want to replace them during a tests.
Lets' say import app.bot will hard to test and patch
I had tried a multiple solutions but failed with them:
Option 1:
Create some base class with which will accepts set of such objects (db, bot, etc).
Every logic class (who need this set) will inherit this class.
AFAIK the similar approach there in SqlAlchemy ORM.
So the code will looks like:
app.config.py:
Class Config:
db: DB
...
tests.py:
import app.config
Config.db = Mock()
create_app.py:
import app.config
def create_app(db):
app.config.Config.db = db
logic.py
import app.config
User(app.config.Config):
def handle_text(text):
self.db.save_text(text=text)
...
The problem with this case is that most likely you can't importing as from app.config import Config
because it will lead to wrong behavior and this is implicit restriction.
Option 2
Pass this set in __init__ arguments to every instance.
(It's ma be a problem if app has many classes, > 20 like in my app).
User:
def __init__(..., config: ProductionConfig):
...
Option 3
In many backend frameworks (flask for example) there are context object.
Well we can inject our config into this context during initialization.
usage.py:
my_handler(update, context):
context.user.handle_text(text=update.text, db=context.db)
The problem with this approach is that every time we need to pass context to access a database in our logic.
Option 4
Create config by condition and import it directly.
This solution may be bad because conditions increases code complexity.
I'm following rule "namespace preferable over conditions".
app.config.py:
db = get_test_db() if DEBUG else get_production_db()
bot = Mock() if DEBUG else get_production_bot()
P.S. this question isn't "opinion based" because in some point the wrong solutions will leads to bad design and bugs therefore.
I am trying to get EhCache configured to handle authorization caching in my Apache Shiro enabled web service. Currently I am getting the following exception:
org.apache.shiro.cache.CacheException: net.sf.ehcache.CacheException: Another unnamed CacheManager already exists in the same VM. Please provide unique names for each CacheManager in the config or do one of following:
Use one of the CacheManager.create() static factory methods to reuse same CacheManager with same name or create one if necessary
Shutdown the earlier cacheManager before creating new one with same name.
My shiro.ini looks like:
[main]
...
cacheManager = org.apache.shiro.cache.ehcache.EhCacheManager
cacheManager.cacheManagerConfigFile = classpath:ehcache.xml
securityManager.cacheManager = $cacheManager
From this StackOverflow post it looks like people using Spring have gotten around this issue by forcing the CacheManager to be a singleton: Another unnamed CacheManager already exists in the same VM (ehCache 2.5).
Is anybody aware of work-arounds not using Spring initialization (I'm working within the dropwizard framework and have no need to pull in Spring)? Is there some manner of enforcing singleton configuration from the shiro.ini?
Thank you in advance!
Create a custom class that extends EhCacheManager and set your cacheManager in the constructor. This (net.sf.ehcache.CacheManager.create()) allows you to reuse an already existing cachemanager.
package lekkie.omotayo
public class MyShiroCacheManager extends EhCacheManager
{
public CacheManager()
{
setCacheManager(net.sf.ehcache.CacheManager.create());
}
}
Then you can do this:
cacheManager = lekkie.omotayo.MyShiroCacheManager
cacheManager.cacheManagerConfigFile = classpath:ehcache.xml
securityManager.cacheManager = $cacheManager
We have a situation where we have multiple databases with identical schema, but different data in each. We're creating a single session factory to handle this.
The problem is that we don't know which database we'll connect to until runtime, when we can provide that. But on startup to get the factory build, we need to connect to a database with that schema. We currently do this by creating the schema in an known location and using that, but we'd like to remove that requirement.
I haven't been able to find a way to create the session factory without specifying a connection. We don't expect to be able to use the OpenSession method with no parameters, and that's ok.
Any ideas?
Thanks
Andy
Either implement your own IConnectionProvider or pass your own connection to ISessionFactory.OpenSession(IDbConnection) (but read the method's comments about connection tracking)
The solution we came up with was to create a class which manages this for us. The class can use some information in the method call to do some routing logic to figure out where the database is, and then call OpenSession passing the connection string.
You could also use the great NuGet package from brady gaster for this. I made my own implementation from his NHQS package and it works very well.
You can find it here:
http://www.bradygaster.com/Tags/nhqs
good luck!
Came across this and thought Id add my solution for future readers which is basically what Mauricio Scheffer has suggested which encapsulates the 'switching' of CS and provides single point of management (I like this better than having to pass into each session call, less to 'miss' and go wrong).
I obtain the connecitonstring during authentication of the client and set on the context then, using the following IConnectinProvider implementation, set that value for the CS whenever a session is opened:
/// <summary>
/// Provides ability to switch connection strings of an NHibernate Session Factory (use same factory for multiple, dynamically specified, database connections)
/// </summary>
public class DynamicDriverConnectionProvider : DriverConnectionProvider, IConnectionProvider
{
protected override string ConnectionString
{
get
{
var cxnObj = IsWebContext ?
HttpContext.Current.Items["RequestConnectionString"]:
System.Runtime.Remoting.Messaging.CallContext.GetData("RequestConnectionString");
if (cxnObj != null)
return cxnObj.ToString();
//catch on app startup when there is not request connection string yet set
return base.ConnectionString;
}
}
private static bool IsWebContext
{
get { return (HttpContext.Current != null); }
}
}
Then wire it in during NHConfig:
var configuration = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2005
.Provider<DynamicDriverConnectionProvider>() //Like so
In SQL Server 2005, is there a way to specify more than one connection string from within a .NET Application, with one being a primary preferred connection, but if not available it defaults to trying the other connection (which may be going to a diff DB / server etc)?
If nothing along those exact lines, is there anything we can use, without resorting to writing some kind of round-robin code to check connections?
Thanks.
We would typically use composition on our SqlConnection objects to check for this. All data access is done via backend classes, and we specify multiple servers within the web/app.config. (Forgive any errors, I am actually writing this out by hand)
It would look something like this:
class MyComponent
{
private SqlConnection connection;
....
public void CheckServers()
{
// Cycle through servers in configuration files, finding one that is usable
// When one is found assign the connection string to the SqlConnection
// a simple but resource intensive way of checking for connectivity, is by attempting to run
// a small query and checking the return value
}
public void Open()
{
connection.Open();
}
public ConnectionState State
{
get {return connection.State;}
set {connection.State = value;}
}
// Use this method to return the selected connection string
public string SelectedConnectionString
{
get { return connection.ConnectionString; }
}
//and so on
}
This example includes no error checking or error logging, make sure you add that, so the object can optionally report which connections failed and why.
Assuming that you'd want to access the same set of data, then you'd use clustering or mirroring to provide high availability.
SQLNCLI provider supports SQL Server database mirroring
Provider=SQLNCLI;Data Source=myServer;Failover Partner=myMirrorServer
Clustering just uses the virtual SQL instance name.
Otherwise, I can't quite grasp why you'd want to do this...
Unfortunately there are no FCL methods that do this - you will need to implement this yourself.
I am using the HybridSessionBuilder supplied by Palermo and his team .. link ..
We have our staging environments set up so that the url will be one of the following based on the environment
web-test.company.com
web-cert.company.com
web.company.com
what we normally do is take a look at the url and if it has "-test" we use the test configurations and so on (connection strings, etc).
This is the first project that uses nhibernate in this type of environment. What would be a good way to tell the Session Builder to use the correct hibernate cfg (I will build 1 for each environment).
The HybridSessionBuilder lives in an infrastructure layer and is injected into repositories via StructureMap.
Here's how I select a single configuration file using the HybridSessionBuilder:
public Configuration GetConfiguration()
{
var configuration = new Configuration();
string cfgFile = Path.GetDirectoryName(Assembly.GetAssembly(this.GetType()).CodeBase) +
"\\com.Data.nHibernate.cfg.xml";
configuration.Configure(cfgFile);
configuration.AddAssembly("com.Data");
return configuration;
}
If you want to select configuration files based on the URL I would just identify the call stack that leads to this function and pass in either an enum value or the config file's name directly.