Create parameterized Persistence Unit + JTA DataSource at Runtime (context dependent) - persistence

i'm trying to write an EJB3 Stateless Session Bean which gets the parameter "customerCode" (String).
Dependent on this "customerCode" i want to create an EntityManager (Persistence.createEntityManagerFactory...) with a (dynamically?) created PersistenceUnit.
I can not define the PU in the persistence.xml, because it's name (and underlying datasource) must be able to be added/removed at runtime (e.g. deploying a new datasource/persistence unit that belongs to a specific customer code).
I could define the PUs in the persistence.xml, because i know all the customerCodes in advance, but if the datasource XML file is missing, i can not deploy my EAR correctly, because the container (JBOSS) looks for a matching datasource.
what can i do?
thanks in advance!

Yes you can do this.A rough cut is below.
private static Map<String, EntityManagerFactory> emfMap
= new HashMap<String, EntityManagerFactory>();
private static List<String>customerCodes;
You need to populate this list of customerCodes obviously before calling populateEmfMap
public static void populateEmfMap()
{
for (String customerCode : customerCodes)
{
emfMap.put(customerCode,Persistence.createEntityManagerFactory(customerCode));
}
}
You can just get it from the Hasmap by key.

Related

registering DbContext with multiple parameters

I'm trying to inject TenantProvider into DbContext
public class AppDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, long>
{
public int? _tenantId;
public ITenantProvider _tenantProvider;
public AppDbContext(
DbContextOptions<AppDbContext> options,
ITenantProvider tenantProvider
)
: base(options)
{
_tenantProvider = tenantProvider;
}
but I don't understand how to register it correctly - if I put the breakpoint in the constructor - tenantProvider is null.
The bit from Startup.cs
services.AddDbContext<AppDbContext>(options => AppDbContextOptionsBuilder.Get());
the next line is required to inject the DbContext into a controller or a service (if I add ServiceLifetime.Scoped as a second parameter to the method above - AddDbContext - the feature doesn't work):
services.AddScoped(p => new AppDbContext(AppDbContextOptionsBuilder.Get(), p.GetService<ITenantProvider>()));
(Entity Framework is a separate project in my solution)
When using .AddScoped method - we can pass TenantProvider into constructor by resolving it using .GetService method.
Does anyone have an idea of how to resolve TenantProvider in .AddDbContext method?
Additional info:
I was trying to replace ITenantProvider in the constructor of DbContext with IHttpContextAccessor - the latter is registered as singleton. But the acessor parameter is still null.
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
I don’t really understand what your AddScoped call is supposed to do. AddDbContext will already register the database context properly with the service collection. So when you resolve the context through dependency injection, additional dependencies will be automatically resolved.
So it should be enough to do this:
services.AddDbContext<AppDbContext>(options => …);
services.AddSingleton<ITenantProvider, TenantProvider>();
And then, you can depend on your AppDbContext using constructor injection, e.g. in your controllers.
Two notes though:
When configuring options, you should modify the passed options object. So you should not just return AppDbContextOptionsBuilder.Get() but instead use the passed options object and edit that.
You should really think about whether your database context having a dependency on your tenant provider is the right thing to do. As per SRP, your database should only do a single thing and that is provide database access.
Depending on how your tenant provider affects your database access, it might make more sense to move this dependency up one level into some service that uses both the database context and the tenant provider to query data in the right way.

Configuration for EJB lookups at runtime

I have several services deployed as EJBs on a JBoss-AS-7.1 server. Many applications use these EJBs by doing a lookup like this:
#EJB(lookup = "java:global/FooService/FooBean!com.xyz.FooBeanRemote")
private FooBeanRemote fooBeanRemote;
The problem is that the lookup string is hard-coded in the source. I want to be able to change this lookup at runtime - without a re-compilation - because FooService may be updated some time in the future, and perhaps have a different implementation. In addition, the ejb could also move to a different server instance.
What would be the best way to achieve this?
Use ejb-jar.xml instead of annotation (check here)
use InitialContext in your code to lookup for bean and move bean name to properties file
Implement CDI producer methods in separate jar
--EDIT---
Quick HOWTO about last point:
1. Create qualifier
#Qualifier
#Retention(RUNTIME)
#Target({FIELD, TYPE, METHOD})
public #interface FooService {
}
2. Create producer method
public class EJBProducer {
#Produces
#FooService
#EJB(lookup = "java:global/FooService/FooBean!com.xyz.FooBeanRemote")
private FooBeanRemote fooBeanRemote;
}
3. Use in your code
#Inject #FooService
private FooBeanRemote fooBeanRemote;
Two first points may be in another jar archive (remember to include there META-INF/beans.xml file). You can also use producer method instead of field, and access ejb programmatically.

JPA entity manager from Datasource during runtime

I'm wondering if there is possibility to create EntityManager from defined datasource in AS during runtime via JNDI lookup. Imagine that administrator configures a new datasource within the AS (TomEE, JBoss, Glassfish... it could be any JEE6 AS) and I want to use this datasource only by providing JNDI name of this datasource in my application.
String datasourceName = "java:/myDS";
Datasource/Resource datasource = // some JNDI lookup via datasourceName
EntityManager em = // some magic, maybe with EntityManagerFactory
Note that it would be nice to stay in Java EE 6 specification and not use any vendor specific implementation.
It has been almost 3 years, so I suppose there is no easy way to do so.
I'm closing this question. If anyone finds solution in the future, you may post answer and I will re-check the correct answer.
I suggest to create two entityManagerFactory object and inject properties using #PersistenceUnit(unitName='') and create entityManager from factory object and use within a transaction context and then clear it.
Class EntityManagerProducer{
#PersistenceUnit(unitName='')
EntityManagerFactory emf1;
#PersistenceUnit(unitName='')
EntityManagerFactory emf2;
EntityManager getEm1()
{
return emf1.createEntityManager();
}
EntityManager getEm2()
{
return emf2.createEntityManager();
}
}

Static use of Dozer Mapper

Just wondering if having a static dozer mapper like this can leads to concurrency errors :
public static Mapper mapper = new DozerBeanMapper();
public static MyDTO toDTO(MyEntity e) {
MyDTO dto = mapper.map(e, MyDTO.class);
return dto;
}
Or should I always use this code :
public static MyDTO toDTO(MyEntity e) {
Mapper mapper = new DozerBeanMapper();
MyDTO dto = mapper.map(e, MyDTO.class);
return dto;
}
The method is used in an #Stateless session bean of a JBoss Server, it can be accessed concurrently. The fact is I dont really know if Dozer makes use of static variables or instance variables in the library to decide if I can/should use a static Mapper or create a new instance at every call.
Dozer instance could be static. If you would create new instance for each request the performance will be much worse, since lots of the caches will be initialised every time. ConcurrencyErrors may be encountered either due to bugs in Custom Converters or internal Dozer problems.
From the documentation, DozerMapper instance should be built as singleton. The DozerBeanMapper is thread safe so you can use at any risks with multiple threads.
To be sure you can also use DozerBeanMapperSingletonWrapper.getInstance(); This will handle the singleton part for you.
I don't thinks it is a really good idea to use the mapper as public static field.
You could also use Selma, to handle youre mapping. This is a new library based on an Annotation processor that generates the mapping code at compile time. With it youre code will look like that:
// Configure the mapping
#Mapper
public interface DtoMapper {
MyDTO toDTO(MyEntity e);
}
// Retrieve the mapper
public static DtoMapper mapper = Selma.getMapper(DtoMapper.class);
// and some where in the code use
mapper.toDto(entity);

Using JasperReports with datasources which rely on CDI

I have some classes which use CDI injected beans in their getters, e.g.:
class MyBean() {
#Inject
private TranslationBean translationBean;
private String chosenValue;
public void setChosenValue(String c) { chosenValue = c;}
public String getChosenValue() {
return translationBean.getTranslatedValue(chosenValue);
}
}
The underlying chosenValue is loaded from and persisted into a database.
Now I want to create a JasperReport generated PDF with such beans as DataSource. I call:
JasperFillManager.fillReport("myFile.jasper", new HashMap<String, Object>(), new JRBeanCollectionDataSource(Arrays.asList(myBean));
Obviously, the error message from Weld will eventually be that no context is active.
I now see two possibilities:
create a wrapping class for MyBean especially for JasperReports in which all needed fields are filled with actual data and no CDI dependencies are needed. Problem would be: a LOT of coding with a lot of boilerplate and repeating code.
Somehow manage to wrap a context around the call to the JasperFillManager so it runs within an/the current active CDI context.
Would the second option be possible? Is there any other, nicer way than one of the proposed ones?
You're probably looking at creating a new scope, if its possible to wrap all the JasperStuff. Take a look at the Seam Reports stuff in https://github.com/seam/reports, it may be of some help or inspiration.