Accessing Datasource from Outside A Web Container (through JNDI) - jboss

I'm trying to access a data source that is defined within a web container (JBoss) from a fat client outside the container.
I've decided to look up the data source through JNDI. Actually, my persistence framework (Ibatis) does this.
When performing queries I always end up getting this error:
java.lang.IllegalAccessException: Method=public abstract java.sql.Connection java.sql.Statement.getConnection() throws java.sql.SQLException does not return Serializable
Stacktrace:
org.jboss.resource.adapter.jdbc.remote.WrapperDataSourceService.doStatementMethod(WrapperDataSourceS
ervice.java:411),
org.jboss.resource.adapter.jdbc.remote.WrapperDataSourceService.invoke(WrapperDataSourceService.java
:223),
sun.reflect.GeneratedMethodAccessor106.invoke(Unknown Source),
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25),
java.lang.reflect.Method.invoke(Method.java:585),
org.jboss.mx.interceptor.ReflectedDispatcher.invoke(ReflectedDispatcher.java:155),
org.jboss.mx.server.Invocation.dispatch(Invocation.java:94),
org.jboss.mx.server.Invocation.invoke(Invocation.java:86),
org.jboss.mx.server.AbstractMBeanInvoker.invoke(AbstractMBeanInvoker.java:264),
org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:659),
My Datasource:
<?xml version="1.0" encoding="UTF-8"?>
<datasources>
<local-tx-datasource>
<jndi-name>jdbc/xxxxxDS</jndi-name>
<connection-url>jdbc:oracle:thin:#xxxxxxxxx:1521:xxxxxxx</connection-url>
<use-java-context>false</use-java-context>
<driver-class>oracle.jdbc.driver.OracleDriver</driver-class>
<user-name>xxxxxxxx</user-name>
<password>xxxxxx</password>
<exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter</exception-sorter-class-name>
<min-pool-size>5</min-pool-size>
<max-pool-size>20</max-pool-size>
</local-tx-datasource>
</datasources>
Does anyone have a clue where this could come from?
Maybe someone even knows a better way how to achieve this.
Any hints are much appreciated!
Cheers,
Michael

Not sure if this is the same issue?
JBoss DataSource config
DataSource wrappers are not usable outside of the server VM

#Michael Well, java.sql.Connection is an Interface - it might technically be possible for the concrete implementation you're getting from JBoss to be Serializable - but I don't think you're really going to have any options you can use. If it was possible, it would probably be easy :)
I think #toolkit might have said the right words with useable outside the VM - the JDBC drivers will be talking to native driver code running in the underlying OS I guess, so that might explain why you can't just pass a connection over the network elsewhere.
My advice, (if you don't get any better advice!) would be to find a different approach - if you have access to locate the resource on the JBoss directory, maybe implement a proxy object that you can locate and obtain from the directory that allows you to use the connection remotely from your fat client. That's a design pattern called data transfer object I think Wikipedia entry

#toolkit:
Well, not exactly. Since I can access the data source over JNDI, it is actually visible and thus usable.
Or am I getting something totally wrong?
#Brabster:
I think you're on the right track. Isn't there a way to make the connection serializable? Maybe it's just a configuration issue...

I've read up on Ibatis now - maybe you can make your implementations of Dao etc. Serializable, post them into your directory and so retrieve them and use them in your fat client? You'd get reuse benefits out of that too.
Here's an example of something looks similar for Wicket

JBoss wraps up all DataSources with it's own ones.
That lets it play tricks with autocommit to get the specified J2EE behaviour out of a JDBC connection. They are mostly serailizable. But you needn't trust them.
I'd look carefully at it's wrappers. I've written a surrogate for JBoss's J2EE wrappers wrapper for JDBC that works with OOCJNDI to get my DAO code unit test-able standalone.
You just wrap java.sql.Driver, point OOCJNDI at your class, and run in JUnit.
The Driver wrapper can just directly create a SQL Driver and delegate to it.
Return a java.sql.Connection wrapper of your own devising on Connect.
A ConnectionWrapper can just wrap the Connection your Oracle driver gives you,
and all it does special is set Autocommit true.
Don't forget Eclipse can wrt delgates for you. Add a member you need to delegate to , then select it and right click, source -=>add delgage methods.
This is great when you get paid by the line ;-)
Bada-bing, Bada-boom, JUnit out of the box J2EE testing.
Your problem is probably amenable to the same thing, with JUnit crossed out and FatCLient written in an crayon.
My FatClient uses RMI generated with xdoclet to talk to the J2EE server, so I don't have your problem.

I think the exception indicates that the SQLConnection object you're trying to retrieve doesn't implement the Serializable interface, so it can't be passed to you the way you asked for it.
From the limited work I've done with JDNI, if you're asking for an object via JNDI it must be serializable. As far as I know, there's no way round that - if I think of a better way I'll post it up...
OK, one obvious option is to provide a serializable object local to the datasource that uses it but doesn't have the datasource as part of its serializable object graph. The fat client could then look up that object and query it instead.
Or create a (web?) service through which to access the datasource is governed - again your fat client would hit the service - this would probably be better encapsulated and more reuseable approach if those are concerns for you.

Related

How do I detect whether a mongodb serializer is already registered?

I have created a custom serializer for mongoDB.
I can register it and it works as expected.
However the my application sometimes throws an error because it tries to register the serializer twice.
How do I detect whether a serializer has already been registered and thus stop my application from registering a second time?
If you are using
BsonSerializer.RegisterSerializer(typeof (Type), typeSerializer);
you might get this error "there is already a serializer registered for type". Because you cannot register the same type of serializer 2 times. But you can write your own serializer and this serializer will work before default serializers.
For instance: if you want to use local DateTime instead of Utc which is default.
all you need to do is that writing a class implementing IBsonSerializationProviderand register this provider to BsonSerializer as soon as possible!
here is the sample code.
public class LocalDateTimeSerializationProvider : IBsonSerializationProvider
{
public IBsonSerializer GetSerializer(Type type)
{
return type == typeof(DateTime) ? DateTimeSerializer.LocalInstance : null;
}
}
and to be able to register
BsonSerializer.RegisterSerializationProvider(new LocalDateTimeSerializationProvider());
I hope this helps, you can also read the original documentation in here
this .net driver version of mongodb is 2.4!
TL;DR: Ig you are lazy, use BsonSerializer.LookupSerializer or BsonMemberMap.GetSerializer. To do it right, make sure the registration code is called once and only once.
The best approach to avoid this is to make sure the serializer is registered only once. It's a good idea to have some global startup code that registers anything that is global to the application once, and only once. That includes stuff like dependency injector configuration, tools like automapper and the mongodb driver. If you call this code only once and from a single point in code, you don't need to worry about thread safety, dead locks or similar troubles.
The MongoDB driver configuration settings are thread-safe, but don't assume that this is true for all software packages that you might need to configure. Also, locking can be very expensive performance wise if your code is multi-threaded, for instance in a web-application. Last but not least, that lookup you're doing might not be trivial in the first place, because some methods need to walk an entire inheritance tree.

Utilizing RijndaelManaged, Enterprise Library and Autofac together

I'm newly experimenting with the cryptography application block while using Autofac as the container.
As a result, I'm using the nuget package EntLibContrib 5.0 - Autofac Configurator.
With the DPAPI Symmetric Crypto Provider, I was able to encrypt/decrypt data just fine.
However, with RijndaelManaged, I receive an ActivationException:
Microsoft.Practices.ServiceLocation.ActivationException: Activation error occured while trying to get instance of type ISymmetricCryptoProvider, key "RijndaelManaged" ---> Autofac.Core.Registration.ComponentNotRegisteredException: The requested service 'RijndaelManaged (Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.ISymmetricCryptoProvider)' has not been registered. To avoid this exception, either register a component to provide the service, check for service registration using IsRegistered(), or use the ResolveOptional() method to resolve an optional dependency.
Per instructions here: http://msdn.microsoft.com/en-us/library/ff664686(v=pandp.50).aspx
I am trying to inject CryptographyManager into MyService.
My bootstrapping code looks like this:
var builder = new ContainerBuilder();
builder.RegisterEnterpriseLibrary();
builder.RegisterType<MyService>().As<IMyService>();
_container = builder.Build();
var autofacLocator = new AutofacServiceLocator(_container);
EnterpriseLibraryContainer.Current = autofacLocator;
App.config has this info defined for symmetricCryptoProviders:
name: RijndaelManaged
type: Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.HashAlgorithmProvider, Microsoft.Practices.EnterpriseLibrary.Security.Cryptography, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
algorithmType:System.Security.Cryptography.RijndaelManaged
protectedKeyFilename:[path_to_my_key]
protectedKeyProtectionScope: LocalMachine
Anyone have experience in this combination of technologies?
After some testing, I believe I may go with a Unity container instead, since I have no preference in IOC containers other than whatever I use should integrate nicely with ASP.NET MVC3 and http-hosted WCF services.
My bootstrapping code then becomes more simple:
var container = new UnityContainer()
.AddNewExtension<EnterpriseLibraryCoreExtension>();
container.RegisterType<IMyService, MyService>();
I actually wrote the Autofac EntLib configurator (with some help from some of the P&P folks). It's been tested with the exception handling block and logging block, but I haven't tried it with the cryptography stuff.
EntLib has an interesting thing where it sometimes requires registered services to be named, and I'm guessing from the exception where it says...
type ISymmetricCryptoProvider, key "RijndaelManaged"
...I'm thinking EntLib wants you to register a named service, like:
builder.Register(c =>
{
// create the HashAlgorithmProvider using
// RijndaelManaged algorithm
})
.Named<ISymmetricCryptoProvider>("RijndaelManaged");
I'm sort of guessing at the exact registration since, again, I've not got experience with it or tested it, but the idea is that EntLib is trying to register a named service whereas the actual service isn't getting registered with the name.
The RegisterEnterpriseLibrary extension basically goes through and tries to use the same algorithm that Unity uses to do the named/unnamed registrations. I'm guessing you've encountered an edge case where something's not getting handled right. EntLib is pretty well tied to Unity, even if they did try to abstract it away.
If you're not tied to Autofac, Unity is going to be your lowest-friction path forward. I like the ease of use and more lightweight nature of Autofac, and my apps are tied to it, so I needed everything to work that way; if you don't have such an affinity, might be easier to just use Unity.
Sorry that's not a super answer. EntLib wire-up in IoC is a really complex beast.

GWT RPC: hotswap vs POJO

I have encountered following problem.
Currently I'm working with colleague on GWT project.
We are using RPC async service. We often need to send and receive state object which is a HashMap.
We have bunch of service methods which are always have state as parameter and as a return type:
HashMap<String, Serializable> fillAndGetUI(HashMap<String, Serializable> state) throws ProjectServiceException;
I'm telling not to use this because we have Serializable interface in method declaration which is not good for RPC and GWT compilation.
But: HashMap is useful while we can use hotswap instead of restarting server each time (it's enough to write method put and get).
My suggestion was to use POJO, but we can loose hotswap abliliy which is critical.
What is the solution to not use HashMap in declarations and have Hotswap ability in the same time ? Can RequestFactory solve this issue? (We are using GWT 2.1. version change is not an option)
The easiest solution use plain old RequestBuilder, JSON and Overlay Types. RequestFactory will not help you

WCF Data Service with EF fails to expose imported functions

(I am also using .NET 4.0 and VS 2010.)
I created a function import returning a complex type, as explained at http://msdn.microsoft.com/en-us/library/bb896231.aspx. The function import and new complex type appear in my .edmx file and in the Designer.cs file. However, the function does not appear when I view the service in the browser, and when I add or update a service reference in the client project, the function does not appear there either - as is to be expected, given the first result.
Creating an imported function and using it seems conceptually very simple and straightforward, and one would think it would just work, as Microsoft's step-by-step instructions appear to suggest: http://msdn.microsoft.com/en-us/library/cc716672.aspx#Y798 (which article shows the SP returning entity types - I tried this also, and it doesn't work for me either).
This blog post shows the addition of a method to the DataService class, which Microsoft's instructions omit: http://www.codegain.com/articles/wcf/miscellaneous/how-to-use-stored-procedure-in-wcf-data-service.aspx I tried adding one method returning a list of entity types and another returning a list of complex types, and still had no success. I still could not access the functions, either directly via the browser or from the client application via a service reference.
Thanks in advance for any help with this.
config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
MS would do well to add a note to the walkthroughs stating that the above bit of code must be there. (It may be better to enable each operation explicitly than to use "*".)
http://www.codegain.com/articles/wcf/miscellaneous/how-to-use-stored-procedure-in-wcf-data-service.aspx shows that line of code. Also, something it is there in the code, commented out, when one creates the WCF Data Service. Some of us like to delete commented-out code that we aren't using and that seems irrelevant - perhaps doing so a bit prematurely, sometimes.

Where should I put my connectionString in ASP.Net 3.5?

I have two projects:
ASP.Net 3.5 website (frontend, UI)
VB Class Library (dataaccess logic)
Where should I save my connectionString, so that I can use if from the class library? And how does this affect where it is placed when I deploy/publish?
Note:
I don't want to pass it to every function in my VB Class
Depending on how you constructed your DAL -- LINQ, TableAdapters, etc. -- it may automatically look for it in the web.config file. If you created the DAL via a designer, likely it stores the default connection string in the app.config file for you class library. I copy the connection strings section from the app.config file to my web.config and change the connection string to the correct database (I have separate web.config's for DEV/QA/PROD). This makes it trivial since the designer generated code already has the code implemented to retrieve it from the configuration file.
If you are hand-coding your DAL and need to pass in the connection string, I suggest setting up a strongly-typed configuration class that interfaces to the web.config and does lazy loading of your configuration values. Use a factory to create your DAL and inject the configuration class into your factory via constructor so that it knows how to create your DAL with the connectionsString retrieved from the configuration file.
My question came from having spent half a day of trying to make this work, but I kept getting the wrong connection when deploying (where I use another database).
My problem was, that I was using
My.Settings.DefaultConnectionString
...To retrieve the connectionString in my VB Class Library.
After following tvanfossons anwer, I dug around some more and found out, that I can simply use (after referencing system.configuration) :
System.Configuration.ConfigurationManager.ConnectionStrings.Item("DefaultConnectionString").ConnectionString
It looks in the web-config for webapplications and app.config for windows/class library apps.
I am glad it now works, but even more glad I know why. ;)
I had the same issue you were having and I ended up using the System.Configuration.ConfigurationManager class to obtain the connection string stored in my web.config file from my class library like Kjensen's answer suggested. This worked wonders, if I had more experience I would vote that answer up.
I needed the connection string to build my Linq2Sql data context, which this method provided me with.
I now build my data context like below (remembering to add a reference to System.Configuration) -
public MyDataContext() : base(System.Configuration.ConfigurationManager.ConnectionStrings["MyConnectionString"]
.ConnectionString, mappingSource)
And as long as the web.config file contains "MyConnectionString" the configuration manager takes care of the rest.
We keep ours in the machine.config of each server and have a custom DAL to handle all DB interaction for our web apps.
Put it in the web.config in the connection strings section.
In the VB project use HttpContext.Current.GetSection to retrieve the section.
A fellow developers idea once was that we should store all the connection strings in a database table.
Don't try doing that. You won't get very far. :)