There is an application that talks to LDAP on a need basis for several operations like user info fetch, list of users, list of groups, email ids etc. Every time a request has to be made an InitialDirContext object is created and used as follows.
Properties ldapProperties = new Properties();
ldapProperties.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
ldapProperties.put(Context.PROVIDER_URL, "ldaps://serv:636");
ldapProperties.put(Context.SECURITY_AUTHENTICATION, "simple");
ldapProperties.put(Context.SECURITY_PRINCIPAL, "user");
ldapProperties.put(Context.SECURITY_CREDENTIALS, "password");
ldapProperties.put("java.naming.ldap.attributes.binary", "tokenGroups");
InitialDirContext ctx = new InitialDirContext(ldapProperties);
ctx.search(....);
Should this "ctx" object be closed using the close() method?
If its not closed and there are multiple new InitialDirContext() creations will the old ones be automatically closed?
If it was just an internal object it will be garbage collected but what about this connection object?
No reason to close the context object each time.
You should be aware that it would be possible that the server (or some network device like a Load balancer proxy) would close the connection and then you may need to reinitialize the connection.
We have some Example JNDI solutions you may find helpful.
-jim
Related
This question already has answers here:
Spring-data-mongodb connect to multiple databases in one Mongo instance
(7 answers)
Closed 4 years ago.
I am in the process of finding out how do I dynamically connect to different mongo db's based on the user that logs in. I see multiple posts that talks about it but since I am new to this just wanted to understand more on how to implement it. In our application while creating the user account we could create different db files based on the userName, which acts as a key.
So we know which database to connect so it is just matter of selecting correct Factory I guess.
I see following constructor in the template code.
public MongoTemplate(Mongo mongo, String databaseName) {
this(new SimpleMongoDbFactory(mongo, databaseName), null);
}
My current Spring java config does following
#Bean
public MongoDbFactory mongoDbFactory() throws Exception {
UserCredentials userCredentials =
new UserCredentials(
env.getRequiredProperty(databasePropertyNames.getDBUsernamePropertyName()),
env.getRequiredProperty(databasePropertyNames.getDBPasswordPropertyName()));
return new SimpleMongoDbFactory(mongo().getObject(),
env.getRequiredProperty(databasePropertyNames.getDBNamePropertyName()),
userCredentials);
}
#Bean
public MongoTemplate mongoTemplate() throws Exception {
MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory(), mappingMongoConverter());
mongoTemplate.setWriteConcern(WriteConcern.SAFE);
return mongoTemplate;
}
Questions:-
1.Will there be multiple SimpleMongoDbFactory objects that I need to create based on the user that logged in?
If yes then how do I do it and do I need to maintain that object Map?
2. How would I do set those in mongoTemplate at runtime?
Your help would be highly appreciated:)
Following posts worked well for me
github.com/Loki-Afro/multi-tenant-spring-mongodb
Spring-data-mongodb connect to multiple databases in one Mongo instance
Along with this one has to update the Mongo instance to allow the user from default database to be able to write in to any other database
I'm creating a rptlibrary to share with all the reports in my company.
The library has an oda datasource created and shared to all reports. We want to do some querys from ReportEventAdapter.initialize() to the database to get information from the database. I can acces the datasource in the library in this way:
ReportDesignHandle rdh = (ReportDesignHandle)reportContext.getReportRunnable().getDesignHandle();
DesignSessionImpl ds = rdh.getModule().getSession();
String rsf = ds.getResourceFolder( );
LibraryHandle libhan = ds.openLibrary(rsf + "/my.rptlibrary" ).handle( );
DataSourceHandle datasource = libhan.findDataSource("myDS");
But once I have the datasource, there's no way to get a connection to the database from the datasource. The only way to do this, is creating a classic JDBC connection to the database using the data from the datasource? Is there any way to use a more elegant method to connect to the database from the java handler? Like using pooling, reusing the connection, etc..
Thanks.
We can iterate over dataset values in a report script event, thus if a dataset is defined with a JNDI URL, queries can take advantage of a connection pool.
However it is quite complicated. There is a full example in this topic: the script defined in "getDefaultValueList" event of the report parameter can be moved anywhere in the report and then initialize a global variable. In particular we could move it to "initialize" event, or to "beforeFactory" event (in your case "beforeFactory" is probably what you want).
We've trying recently to use XML-RPC.Net library on our project.
Both server(.Net Remoting) and client have been made according to the instructions we've found on http://xml-rpc.net/.
The connection has been made, we obtain data from the server and so on.
As the title states, now, we'd like to know how to make our XML-RPC server instance, which is created after the first client call, be able to give feedback to a WPF UI.
What we'd like to accomplish is to register an event on a server property so the call could arrive to the UI thread.
We are open to any suggestions in this regard.
Here is the code that registers the channel on server side:
IDictionary props = new Hashtable();
props["name"] = "SubsetHttpChannel";
props["port"] = 5678;
channel = new System.Runtime.Remoting.Channels.Http.HttpChannel(
props,
null,
new XmlRpcServerFormatterSinkProvider()
);
ChannelServices.RegisterChannel(channel, false);
RemotingConfiguration.RegisterWellKnownServiceType( typeof(SubsetServer), "subsetserver.rem", WellKnownObjectMode.Singleton);
This is the code that shows how we'd like to set the property after Server instance is created on the UI:
Server = new SubsetServer();
Server.Machine.OnChangeState += delegate(State actual, State next, Event pEvent)
{
uiWindowInstance.PostMessage(string.Format("Subset Server: {0} -> {1}", actual.Name, next.Name));
};
Technologies used: VS2012, WPF 4.5 and XML-RPC.NET 2.5.0
Thanks in Advance
Thanks to anyone that took the time to read it and try to answer.
I found a solution that fits me for the moment. I'd like to share it with you in the hope someone could give any hints wheter this is a solution that may generate problems in the future.
After analyzing, I found out that both server instances run in the same process. So I've created a Singleton as a property inside my Server.
I've put whatever I need inside the Singleton, so for the delegate I'd like to use in my question, the code now is:
Server = new SubsetServer();
Server.**singleton**.Machine.OnChangeState += delegate(State actual, State next, Event pEvent)
{
uiWindowInstance.PostMessage(string.Format("Subset Server: {0} -> {1}", actual.Name, next.Name));
};
Hope this helps anyone else.
Please comment if you find any flaws.
I'm trying to add a Group to my Active Directory service using the UnboundID LDAP SDK, and keep getting error 503: Will Not Perform.
I have verified I'm using an SSL connection, and that I'm connecting with a user that belongs to the Administrators group, which -unless I'm mistaken - gives him the right to create new entries.
I have also raised the logging level of the LDAP Interface Events all the way to 5, and the event viewer registers a number of events, none of which are useful in explaining why the service is unwilling to perform my create entry operation.
Any ideas on what can be causing this problem?
Below is a sample of the scala code I'm using:
val connection = connect("MyAdminUser", "MyAdminPass")
val addGroupResult = connection.add("CN=TestGroup2,OU=Groups,OU=mydomain,DC=mydomain,DC=local",
new Attribute("objectClass", "top", "group"),
new Attribute("name","TestGroup2"),
new Attribute("sAMAccountName","TestGroup2"),
new Attribute("sAMAccountType","268435456"),
new Attribute("objectCategory","CN=Group,CN=Schema,CN=Configuration,DC=mydomain,DC=local"),
new Attribute("cn","TestGroup2"),
new Attribute("distinguishedName","CN=TestGroup2,OU=Groups,OU=mydomain,DC=mydomain,DC=local"),
new Attribute("instanceType","4"),
new Attribute("groupType","-2147483646")
)
private def connect(user: String, pass: String) = {
val options = new LDAPConnectionOptions()
options.setFollowReferrals(true)
val sslUtil = new SSLUtil(new TrustAllTrustManager())
val socketFactory = sslUtil.createSSLSocketFactory()
new LDAPConnection(socketFactory, options, host, securePort, DN(user), pass)
}
And here's the error message I'm getting:
Exception in thread "main" LDAPException(resultCode=53 (unwilling to perform), errorMessage='0000209A: SvcErr: DSID-031A104A, problem 5003 (WILL_NOT_PERFORM), data 0', diagnosticMessage='0000209A: SvcErr: DSID-031A104A, problem 5003 (WILL_NOT_PERFORM), data 0')
My error was including too many attributes in the Add operation, some of which are not supposed to be set manually but rather by the SAM (Security Account Manager).
The correct code is as follows:
val addGroupResult = connection.add("CN=TestGroup2,OU=Groups,OU=simpleBI,DC=domain,DC=local",
new Attribute("objectClass", "top", "group"),
new Attribute("name","TestGroup2"),
new Attribute("sAMAccountName","TestGroup2"),
new Attribute("objectCategory","CN=Group,CN=Schema,CN=Configuration,DC=domain,DC=local")
)
Note that I've removed a few attributes, including sAMAccountType, which were rejected by AD. I've also removed some redundant ones. I believe what I have is the minimal attribute set that fulfills my needs.
The connection code was unchanged.
I have an application that should use an application role from the database.
I'm trying to make this work with queries that are actually run using Subsonic (2).
To do this, I created my own DataProvider, which inherits from Subsonic's SqlDataProvider.
It overrides the CreateConnection function, and calls sp_appsetrole to set the application role after the connection is created.
This part works fine, and I'm able to get data using the application role.
The problem comes when I try to unset the application role. I couldn't find any place in the code where my provider is called after the query is done, so I tried to add my own, by changing SubSonic code. The problem is that Subsonic uses a data reader. It loads data from the data reader, and then closes it.
If I unset the application role before the data reader is closed, I get an error saying: There is already an open DataReader associated with this Command which must be closed first.
If I unset the application role after the data reader is closed, I get an error saying ExecuteNonQuery requires an open and available Connection. The connection's current state is closed.
I can't seem to find a way to close the data reader without closing the connection.
Do you have to use the role for every query?
If not you can use a SharedDbConnectionScope()
using(var scope = new SharedDbConnectionScope())
{
// within this using block you have a single connection
// that isn't closed until scope.Dispose() is called
// (happens automatically while leaving this block)
// and you have access to scope.CurrentConnection
// Do your init stuff
SetRole(scope.CurrentConnection);
var product = new Product();
product.Code = "12345";
product.Save();
// Revert to normal
UnsetRole(scope.CurrentConnection);
}
The problem is that Subsonic executes its reader with CloseConnection.
If I make it not close the connection I can unset the application role after the reader is closed.
May be you can subscribe to the event like this:
Connection.StateChange += new System.Data.StateChangeEventHandler(Connection_StateChange);
And then do some actions according to the new state of this connection:
if(e.CurrentState== System.Data.ConnectionState.Open)
dbworker.ExecuteCommand("EXEC sp_setapprole application, 'password'");