MySql pooled datasource in standalone JAVA app (no J2EE container, no JNDI, no TOMCAT etc.) - mysql

I've been reading dozens of topics here with no real enlightment: I'm running a standalone java app, on a Synology NAS with Java 8. I also installed MariaDB on the same NAS. So everything is local.
I am able to setup a datasource and get a connection, but I would like to be able to access it in any instance of any of my classes / threads for connection pooling. Everything seem to show that I would need JNDI. But I don't have a J2EE container and this seems overkill for my need. Idem for developping my own implementation of JNDI.
I've seen replies to similar questions where people suggest C3PO. But this is just another datasource implementation. I don't think it solves the standalone app issue with no way to access datasource from anywhere in the code :
How to retrieve DB connection using DataSource without JNDI?
Is there another way to share a datasource across java threads ?
Can I pass the Datasource instance as a parameter to each thread, so
they can get a connection when they need ?
Should I assign a given connection to each thread - also passed as a
parameter ? and in this case, never really close it properly ?
Or should I really install something like tomcat, jboss, jetty ? are
they equivalent ? Is there a super light J2EE container that could
provide JNDI ?
Thanks
Vincent

You could use the singleton pattern, like this for example:
public class DataSourceFactory {
private static DataSource instance = null;
private DataSourceFactory() { }
public static synchronized DataSource getDataSource(){
if(instance == null){
instance = // initialize your datasource
}
return instance;
}
}
Then any from any thread you can call DataSourceFactory.getDataSource() to get a reference to your DataSource object.

Related

Injecting DbContext into FileProvider in ASP.NET Core

I am trying to load some of the views from the database as described in here. So I want to use EF Core in the File provider.
RazorViewEngineOptions has a FileProviders property that you can add your file provider to. The problem is that you have to give it an instace of the file provider. So you'll need to instantiate all of the file providers' dependencies right there in Startup's ConfigureServices method.
Currently I inject an instance of IServiceProvider into the Configure method of Startup. Then I store the instance in a field (called _serviceProvider):
IServiceProvider _serviceProvider;
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IServiceProvider provider)
{
_serviceProvider = provider;
...
}
Then in ConfigureServices I use that field to instanciate the UIDbContext.
services.Configure<RazorViewEngineOptions>(options =>
{
var fileProvider = new DbFileProvider(_serviceProvider.GetService<UIDbContext>());
options.FileProviders.Add(fileProvider);
});
Is there any better way to be able to inject the UIDbContext into the DbFileProvider constructor Or any way to instantiate a UIDbContext inside DbFileProvider without IServiceProvider?
You don't want to use DbContext as a file provider source the way you did.
DbContext isn't thread-safe, so it won't work when you have one single DbContext instance for the whole provider, because multiple requests could call the DbContext and it's operation more than once at the same time, resulting in exception when trying to execute 2 queries in parallel.
You'd have to instantiate a connection (like in the linked article) or DbContext per IFileInfo/IDirectoryContents instance.
DbContextOptions<UIDbContext> should be registered as singleton, so you can resolve it onceinside Configure` w/o any issues and pass it to your provider.
Alternatively you can also call DbContextOptionsBuilder and build/construct a DbContextOptions<T>, but then you have to repeat the configuration for you did inside AddDbContext (i.e. .UseSqlServer()).
However it can be useful, as it allows you to set different settings (i.e. changing the way how includes, errors etc. are logged).

I am not able to store entity using em.merge in broadleaf

I am new to broadleaf application. I am able to run application using tomcat + mysql integration well. Now I want to move on with the development to customize the site project as per my requirement.
I am stuck on the point of persistant in broadleaf site module. I have tried using em.merge that returns my entity but do not save it in database and also tried #Transactional(value="blTransactionManager") but It still problem persists. I have tried bellow code in applicationContext-servlet.xml
<aop:config>
<aop:pointcut id="blMyStoreDao" expression="execution(* com.mycompany.dao.StoreDaoImpl.save*(..))"/>
<aop:advisor advice-ref="blTxAdvice" pointcut-ref="blMyStoreDao"/>
</aop:config>
Here is my controller code
newStore.setCustomer(customer);
newStore.setProductList(new ArrayList<ProductImpl>());
Store getStore=store.save(em, newStore);
System.out.println(getStore.getCustomer().getUsername());
System.out.println("customer fetched: "+customer.getEmailAddress());
Here is my daoimpl code
#Repository("blMyStoreDao")
#Transactional(value="blTransactionManager")
public class StoreDaoImpl implements StoreDao {
#PersistenceContext(unitName="blPU")
protected EntityManager em;
#Transactional(value="blTransactionManager")
public Store save(EntityManager em, Store store) {
System.out.println(em);
System.out.println(store.getCustomer().getUsername());
Store s= em.merge(store);
return s;
}
}
But it also didn't resolve my issue.
Code runs perfectly as it should be, but it doesn't save my entity in database.
Anybody Help. Thanks In advance
There isn't any reason to use <aop:config> especially in applicationContext-servlet.xml (if anywhere it should be in the root application context)
You should use #Transactional(TransactionUtils.DEFAULT_TRANSACTION_MANAGER to annotate your method
It is likely that your class was not being scanned by Spring. In Broadleaf, there is a default component scan set up in applicationContext.xml to scan com.mycompany.core.
I would recommend verifying that your dao is actually scanned by Spring and is initialized as a Spring bean. The fact that the entity manager did not get injected indicates that it did not get loaded by Spring correctly. One way to verify this would be to add an #PostConstruct method and print something or set a breakpoint to verify that it gets hit.

CloudFoundry MySQL Java configuration

I have a Spring MVC app that is running fine on local tomcat etc. Its a Spring 3.1 MVC/Hibernate app.
I am using (where possible) pure Java #Configuration for the app - and I am now trying to deploy the app to CloudFoundry (via STS), but I am struggling to get the MySql db configured (from memory, with xml config you dont need to do anything and Spring/CloudFoundry auto-injects the required user/password etc, but its been a while since I deployed anything to CF).
I have tried both of the following configurations:
#Bean
public BasicDataSource dataSource() throws PropertyVetoException {
//CloudFoundry config
final CloudEnvironment cloudEnvironment = new CloudEnvironment();
final List<MysqlServiceInfo> mysqlServices = cloudEnvironment.getServiceInfos(MysqlServiceInfo.class);
final MysqlServiceInfo serviceInfo = mysqlServices.get(0);
BasicDataSource bean = new BasicDataSource();
bean.setDriverClassName("com.mysql.jdbc.Driver");
bean.setUrl(serviceInfo.getUrl());
bean.setUsername(serviceInfo.getUserName());
bean.setPassword(serviceInfo.getPassword());
return bean;
}
The above failed on out of bounds on the .get(0) line of the mysqlServices. This was based on the answer suggested here.
I also tried leaving the datasource as what it runs on as local to see if the properties just get injected, but no luck there either. (the below was tried with the values as per the Spring sample code here, and also using property placeholders from my db.connection props file)
#Bean
public BasicDataSource dataSource() throws PropertyVetoException {
BasicDataSource bean = new BasicDataSource();
bean.setDriverClassName("com.mysql.jdbc.Driver");
bean.setUrl("");
bean.setUsername("spring");
bean.setPassword("spring");
return bean;
}
Edit
I have also used the getServiceInfo(String, Class) method passing in the name of the MySql service that I have created and bound to the application, but that just NPEs similar to the getServiceInfos(..) approach
Ok, this was just a stupid mistake - when I deployed the app via STS I had selected Java Web app rather than the "Spring" type. Not sure why that would make the CloudEnvironment properties not be available (I was under the impression that approach was the common method to inject the details in non-Spring apps) - but re-deploying it to the server as a Spring app resolved the probs!

To many EntityCollections in Entity raise "implement IConvertible" exception in RIA Services

I have a Entity object create with the Entity Framework and used in Silverlight with the RIA Services framework.
The Entity in question has two EntityCollections which are included in the IQueriable sent to the client.
The Entity looks like this:
public class Ad:Entity
{
[Include]
public EntityCollection<PublishingDates> PublishingDates {get;set;}
[Include]
public EntityCollection<Notice> Notice {get;set;}
}
The domain service method includes both collection using Include as this:
[Query]
public IQueryable<Ad> GetAds()
{
return this.ObjectContext.Ad.Include("PublishingDates").Include("Notice");
}
On the client side when the service is called and the result returned the following exception was raise : "The object must implement IConvertible".
If only one EntityCollection is included everything works fine. If both, the previously mentioned exception is raise.
[EDIT]
I use MySQL with MySQL Net Connector version 6.3.5. as the database.
I think its a bug in Net Connector, a very similar bug was reported here http://bugs.mysql.com/bug.php?id=55349
EDIT:
Im not sure this applies to your specific case but for me the latest community server (5.5.9) works a lot better. Note that this is the db not .net connector, which seems not to be involved in the errors I got.
I have the same problem now. The interesting thing is my query works excellent with linux-driven Mysql instance but doesn't work on Windows. May be you will succeed moving to Linux

SL4 WCF RIA Query Issue: "Completed" happening before it's really completed?

I have a strange little issue with a WCF RIA service I'm using in a SL4 application. Here is the code for a button click handler I've got:
private void btnTest_Click(object sender, RoutedEventArgs e)
{
LanguageContext context = new LanguageContext();
LoadOperation<Language> op = context.Load(context.GetLanguagesQuery());
op.Completed += (obj, args) =>
{
if (!op.HasError)
{
System.Threading.Thread.Sleep(500);
MessageBox.Show(context.Languages.FirstOrDefault().DisplayName);
}
};
}
Note that there's a Sleep call in the handler. Without that sleep call, I get an exception (A transport-level error has occurred when sending the request to the server. (provider: Shared Memory Provider, error: 0 - No process is on the other end of the pipe.)). If this code is in the "Completed" handler, I figured it was actually, well, completed by the time it got there. Why does it die without the Sleep()? BTW, the Sleep() isn't an option for production, it was just a problem-sovling tool :)
So, If I add "pooling=false" to my connection string, everything works. However, I don't really like that answer. Connection pooling is a good thing. Is there a way to leave it on and have things still work?
I can also reproduce this issue.
For example, I have a unit test that if run twice in succession will fail the second time.
This unit test performs a few things:
1. Drops and recreates the database using a custom Entity Framework 4.1 DbContext Initiailzer
2. Launches a silverlight application
3. Click a button in the silverlight application
At this point the silverlight application makes a call to a wcf ria service to query the database that was just created.
However, every time the unit test is run a second time, I get the same error.
But the error goes away immediately if I click the button again for example.
Setting "Pooling=False" in my connection string did not resolve the issue in my case.
However, I was able to resolve the issue by restarting the web server which hosts the silverlight application and ria service after the database is created.
In my case, I just decided to use Cassini Dev Web Server v4 and run the tests on that web server instead of iis.
Windows 7 Ultimate x64
Visual Studio 2010 SP1
Entity Framework 4.1
WCF RIA Services SP1 for Silverlight 4
Silverlight 4
MSTest
Edit:
Entity Framework 4.1 Update 1 contains a bug fix to remove the need to specify ‘Persist Security Info=True’ in the connection string when using SQL authentication.
http://www.microsoft.com/download/en/details.aspx?id=26825
I am not (yet) sure if the bug is related and might resolve this issue as well.