Update #ViewScoped bean from JAX-RS service - jax-rs

I've got a mishmash of JAX-RS webservices and JSF/CDI beans. Usual display of my #Entitys is from a #ViewScoped JSF bean collecting relevant entities in a #PostConstruct method:
#Named #ViewScoped
public class Manager {
private List<MyEntity> entities; // + getter
private MyEntity instance; // + getter/setter
#PostConstruct
public void init() {
entities = collectEntities();
instance = new MyEntity();
}
public void save() {
instance = persistInstance();
entities.add(instance);
}
// additional methods like collectEntities, persistInstance
}
Normal operation can call manager.save to persist a new entity and display it alongside the old ones.
Now, a JAX-RS service can also create entities that should be in the collection managed by such a scoped bean:
#Path("/myentity")
public class MyEntityService {
#PersistenceContext EntityManager em;
#PUT
public Response save(#FormParam("name") String name) {
MyEntity entity = new MyEntity(name);
em.persist(entity);
return Response.ok(entity.getId()).build();
}
}
The service can be called on a page where there's also a manager instance.
My question is: how can I make the existing manager instance aware of the additional entity, so that a JSF ajax re-render of a manager.entities list will include the entity created by the webservice?
So far, I've tried a CDI event observed by the CDI bean. The event gets fired from the service but is never received by the bean.
As a workaround I can fire a JSF ajax function telling the manager to refresh it's entity list (leveraging <a4j:jsFunction action="#{manager.init()}">, for example). However I'm unsure about the implications: will this expose a timing problem when the user asks for the entity list to be displayed earlier than the initialization can complete (the list isn't shown by default)?
As a total hack I can probably grab the bean from the session in the service and punch my data in. I shudder just thinking about it.

View scope is something that is JSF specific, as a JSF specific CDI context. It is alive only within the scope of the given view. JAX-RS has no specific way that I can think of to access this scope. I don't believe view scope would even have access to the HTTP request.

Related

Working with multiple DbContext instances causes wrong values to be loaded from database Entity Framework Core

I'm writing an ASP.NET Core API in which the dependency injection container provides me with instances of my DbContext class. I set the service lifetime of the DbContext to transient (which means that the container will create a new instance for every class and every request).
builder.Services.AddDbContext<ComparisonInfoContext>(dbContextOptions =>
dbContextOptions.UseSqlServer("Connection string"), ServiceLifetime.Transient, ServiceLifetime.Transient);
Here is my DbContext class:
public class ComparisonInfoContext : DbContext
{
public DbSet<ComparisonInfo> Comparisons { get; set; } = null!;
public ComparisonInfoContext(DbContextOptions<ComparisonInfoContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<ComparisonInfo>().OwnsMany(c => c.DiscrepancyInfos);
}
}
I also have a BackgroundService class called JobChecker which I added by calling:
builder.Services.AddHostedService<JobChecker>();
In JobChecker, I have a function that runs every minute and the first thing that function does is call context.Comparisons.ToListAsync(). The first time the function runs everything works fine, but the second time, this call returns outdated values for some reason (The values it returns used to be in the database but were changed prior to this call being made).
What I think is happening is the following:
JobChecker (the BackgroundService class) receives it's instance of DbContext at the very start of the program.
The function inside JobChecker calls context.Comparisons.ToListAsync() and gets the correct values from the database (no problems here).
Some controller somewhere changes the values in the database using it's own instance of the DbContext.
The function inside JobChecker runs and calls context.Comparisons.ToListAsync(). It sees that it is already tracking instances with the same id which came from the previous call (step 2). These instances were not effected by the changes made by the controller in step 3. It does not materialize the values it got from the database, instead it returns the instances that already exist. This is explained more here: The life of a query
Does anyone know whether this is in fact what is happening? Is it even correct to set the service lifetime of the DbContext class to transient?
Your DB Context might be transient, but the BackgroundService is not. In effect you only have a single instance of the context in the BackgroundService.
I would look at injecting in an DB Context Factory:
services.AddDbContextFactory<ApplicationDbContext>(...)
Then inject one into your background service:
public class MyBackgroundService(IDbContextFactory<ApplicationDbContext> contextFactory)
Then every iteration of your loop in the background service (it sounds like it is running on a timer), you can use this to instantiate a new context.
using (var context = _contextFactory.CreateDbContext())
{
// ...
}
Docs:
https://learn.microsoft.com/en-us/ef/core/dbcontext-configuration/#using-a-dbcontext-factory-eg-for-blazor
I once faced the same problem with you ,and finally fixed it follow the document:
public SomeBackgroundService( IServiceProvider services)
{
......
}
using (var scope = Services.CreateScope())
{
var context = scope.ServiceProvider.GetService<BackgroundServiceProjContext>();
var personlist1 = context?.Person.ToList();
}
I modified the name and the context injected directly into backgroundservice still read the former value:

MIcronaut-Jaxrs #RequestScope create only one object even with multiple requests

I am trying to inject a io.micronaut.runtime.http.scope.RequestScope object into my jaxrs resource. Here I am priting object to see if it creates different objects for each request. But the object created Only once, even when I sent multiple requests.
Is this a known issue ? Any other way to work around this if that's the case.
#RequestScope
public class RequestScopeObjectX {
public RequestScopeObjectX() {
System.out.println("-------------------------"+this);
}
}
And in. my jaxrs resource class I am doing injecting it
#Inject
RequestScopeObjectX objectX;

Controlling lifetime of objects created by factory generated by ToFactory()

I am using the following Ninject related nuget packages in an MVC 5 WebAPI application:
Ninject.MVC5
Ninject.Extensions.Factory
ninject.extensions.conventions
I have a simple repository and a corresponding factory class like so:
public interface ITaskRunner
{
void Run();
}
public interface IRepository<T> where T: class
{
T[] GetAll();
}
public interface IRepositoryFactory<T> where T: class
{
IRepository<T> CreateRepository();
}
I have setup the Ninject bindings using ToFactory() from Ninject.Extensions.Factory like so:
kernel.Bind<ITaskRunner>().To<TaskRunner>().InSingletonScope();
kernel.Bind(typeof(IRepository<>)).To(typeof(Repository<>)).InRequestScope();
kernel.Bind<IRepositoryFactory<Contact>>().ToFactory();
I am using the factory in the following class:
public class TaskRunner : ITaskRunner
{
//MyTask is a simple POCO class(not shown for brevity)
IRepositoryFactory<MyTask> repoFactory = null;
IRepository<MyTask> repo = null;
public TaskRunner(IRepositoryFactory<MyTask> repoFactory)
{
this.repoFactory = repoFactory;
repo = repoFactory.CreateRepository();
}
//implementation elided
}
I am noticing that the call to repoFactory.CreateRepository() always returns the same instance of the factory (dynamic proxy) that Ninject generates.
Question : Is there a way to change/control this behavior and set a "lifetime" such as Transient, PerThread etc. for the instance that "CreateRepository" returns?
In this particular case, tasks might be processed asynchronously on multiple threads and the repository is not thread safe and hence singleton behavior for the instance returned from "CreateRepository" is not desirable.
I'm not sure what you are trying to achieve, but results you are seeing are quite expected because your TaskRunner is bound as Singleton (so constructed once), and you retrieve your repository in the TaskRunner constructor, which again happens once, and so repo is always the same instance. Note this happens regardless of how you bind IRepository and IRepositoryFactory, see Captive Dependency post by Mark Seemann for details http://blog.ploeh.dk/2014/06/02/captive-dependency/.
In fact, if you need to create repo in the constructor, you could just inject IRepository itself. The power of the Factory extension lies in the fact that it allows to resolve instances at runtime, not construction time. For example, if your TaskRunner has Run() method, you can create repository in it, so each task to run can have its own instance.

Invoked Stateless EJB never change

I'm writing a course on EJBs on JBOSS AS 7 and I have some troubles.
I have a simple local stateless EJB :
#Stateless
public class CitationEJB {
String citation ="Hello Citation";
public String getCitation(){
System.out.println("getting citation from :"+this.toString());
return this.citation;
}
public void setCitation(String citation) {
System.out.println("changing citation to : "+citation);
this.citation = citation;
}
#PostConstruct
public void sayHello(){
System.out.println("Hello, I'm a new EJB");
}
}
Then I invoke a EJB via JNDI in a JSF ManagedBean :
#ManagedBean
#SessionScoped
public class CitationBean {
//#EJB trying this time with JNDI
CitationEJB ejb;
public String getCitation() throws NamingException{
ejb = lookupCitationEJB();
return ejb.getCitation();
}
public String getCitation2() throws NamingException{
ejb.setCitation("hello Toto");
CitationEJB ejb = lookupCitationEJB();
return ejb.getCitation();
}
private static CitationEJB lookupCitationEJB() throws NamingException {
Hashtable jndiProperties = new Hashtable();
jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
Context context = new InitialContext(jndiProperties);
String jndiName = "java:global/CitationsDyn/CitationEJB!com.citations.ejb.CitationEJB";
//jndiName = "java:app/CitationsDyn/CitationEJB"; // Works also
return (CitationEJB) context.lookup(jndiName);
}
}
Then I show up the CitationEJB.getCitation() with JSF. Everything works fine except that when I make F5, and so a new request, I always have the same object : when I use CitationEJB.setCitation("Hello toto"), then F5, I do have "Hello Toto" and not a brand new Object.
When I use the #EJB annotation to get the EJB, I have the expected behaviour with a new object for every request.
So what I learned is that the EJB is picked in a pool, but when is it destroyed ? I guess that the JNDI lookup is not bound to a Scope as is a JSF page. But how is it exactly specified ?
The lifecycle of a Stateless Session Bean is managed by the container. A number of instances will be created and placed in an instance pool when the EJB is deployed (for example JBoss 6 creates 10 instances by default). The number can scale up or down based on the demand. The EJBs are generally not destoryed after use, but rather put back in to the pool to be used again and again.
For your application where you want to keep state, a Stateful Session Bean would be the properly choice (or Single Session Bean if you wanted to share state between the instances). With a Stateful Session Bean, the application can cause the EJB to be destoryed by annotating a method with #Remove.

WCF Ria DomainService - Initialize WebService on StartUp

Currently, my DomainService does perform an Initialization of a resource everytime a client is connecting to him. Every client should access the same instance of this resource.
I would like to initialize this resource on the StartUp of the WebService. Is there any chance to do that with WCF Ria Services?
EDIT:
Okay, don't mention it. I wanted to use this for an global DbContext object. This isn't a good idea anyway, because there will be multiple threads managed by the HttpApplication which would access the DbContext simultaneously. I will change my implementation to an "per Thread", respectively "per HttpContext", approach. Thanks anyhow.
You can define a class that contains a static property for that resource. In the DomainService you can then access that property. It would then be initialized only when it is accessed the first time.
Example:
public class ResManager {
public static MyObject {...}
}
In the DomainService:
public IQueryable<SomeClass> GetSomeObjects()
{
// you can access it here and it will not be initialized
// every time the DomainService is called
MyObject obj = ResManager.MyObject;
return new List<SomeClass>().AsQueryable();
}
If you want to initialize it when the Service is started, then you should be able to do that in the Global class.