Why can't I use #EJB with #Named? - ejb

I basically am trying to inject a #Stateless bean with a local interface into a class annotated with #Named! My understanding is that injection is only possible when the injection point is managed (makes perfect sense), so for example it wouldn't be possible to inject into a POJO but you could inject into a Servlet, a JSF managed or another EJB.
I would have thought that it would have been possible to subsequently use it with #Named! However I get a NullPointerException that specifically seems to imply that this in fact doesn't seem possible!?
My classes look like this (stripped for clarity);
#Named
public class EmailUtil {
// Logger-------------------------------------------------------------------
private static final Logger LOG = Logger.getLogger(EmailUtil.class.getName());
// Constructor--------------------------------------------------------------
public EmailUtil() {
}
// EJB----------------------------------------------------------------------
#EJB AuditDAO audit;
// Methods------------------------------------------------------------------
public void sendEmail(
String emailSender,
String emailRecipient,
String emailSubject,
String emailHtmlBody,
String emailTextBody) throws FailedEmailException {
... code removed for clarity ...
// Call Amazon SES to send the message
try {
new SES().getClient().sendEmail(request);
// Create an audit log of the event
audit.create("Email sent to " + emailSender);
} catch (AmazonClientException ace) {
LOG.log(Level.SEVERE, ace.getMessage(), ace);
throw new FailedEmailException();
} catch (Exception e) {
LOG.log(Level.SEVERE, e.getMessage(), e);
}
}
}
#Stateless
public class AuditDAOImpl implements AuditDAO {
// Logger-------------------------------------------------------------------
private static final Logger LOG = Logger.getLogger(AuditDAOImpl.class.getName());
// EntityManager------------------------------------------------------------
#PersistenceContext(unitName = "iConsultPU")
private EntityManager em;
#Override
public void create(String event) {
String subject;
try {
/*
* If the current subject has authenticated and created a session we
* want to register their ID. However it is possible that a subject
* does not have an ID so we want to set it to unknown.
*/
subject = SecurityUtils
.getSubject()
.getPrincipals()
.asList()
.get(1)
.toString();
} catch (Exception e) {
subject = "UNKNOWN";
}
Audit audit = new Audit();
audit.setUserId(subject);
audit.setEventTime(Calendar.getInstance());
audit.setEvent(event);
em.persist(audit);
}
}
#Local
public interface AuditDAO {
public void create(String event);
}
I've tried using #Inject as well but that doesn't seem to work either. Have I misunderstood the specification or just poorly implemented it?

You should be injecting your dependencies. So if your EmailUtil is being manually constructed, injection won't work. It needs to be container managed. So if you use a servlet, or any managed bean, you can #Inject it. CDI injection only works for managed objects.
You can do some additional work arounds, such as manually invoking it against a constructed instance. Take a look at this question for an example like that: Parallel webservices access in a Weld CDI environment

Do you have the beans.xml in the correct location? Injection for #Named (and other CDI beans) is handled by CDI, which isn't started unless you have the beans.xml file in the correct location (WEB-INF for war and META-INF for jar).

Related

Spring OAuth2 Making `state` param at least 32 characters long

I am attempting to authorize against an external identity provider. Everything seems setup fine, but I keep getting a validation error with my identity provider because the state parameter automatically tacked onto my authorization request is not long enough:
For example:
&state=uYG5DC
The requirements of my IDP say that this state param must be at least 32-characters long. How can I programmatically increase the size of this auto-generated number?
Even if I could generate this number myself, it is not possible to override with other methods I have seen suggested. The following attempt fails because my manual setting of ?state=abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz is superceded by the autogenerated param placed after it during the actual request:
#Bean
public OAuth2ProtectedResourceDetails loginGovOpenId() {
AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails() {
#Override
public String getUserAuthorizationUri() {
return super.getUserAuthorizationUri() + "?state=abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
}
};
details.setClientId(clientId);
details.setAccessTokenUri(accessTokenUri);
details.setUserAuthorizationUri(userAuthorizationUri);
details.setScope(Arrays.asList("openid", "email"));
details.setPreEstablishedRedirectUri(redirectUri);
details.setUseCurrentUri(true);
return details;
}
The 6-character setting seems to be set here, is there a way to override this?
https://github.com/spring-projects/spring-security-oauth/blob/master/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/RandomValueStringGenerator.java
With the help of this post:
spring security StateKeyGenerator custom instance
I was able to come up with a working solution.
In my configuration class marked with these annotations:
#Configuration
#EnableOAuth2Client
I configured the following beans:
#Bean
public OAuth2ProtectedResourceDetails loginGovOpenId() {
AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails();
AuthorizationCodeResourceDetails details = new
details.setClientId(clientId);
details.setClientSecret(clientSecret);
details.setAccessTokenUri(accessTokenUri);
details.setUserAuthorizationUri(userAuthorizationUri);
details.setScope(Arrays.asList("openid", "email"));
details.setPreEstablishedRedirectUri(redirectUri);
details.setUseCurrentUri(true);
return details;
}
#Bean
public StateKeyGenerator stateKeyGenerator() {
return new CustomStateKeyGenerator();
}
#Bean
public AccessTokenProvider accessTokenProvider() {
AuthorizationCodeAccessTokenProvider accessTokenProvider = new AuthorizationCodeAccessTokenProvider();
accessTokenProvider.setStateKeyGenerator(stateKeyGenerator());
return accessTokenProvider;
}
#Bean
public OAuth2RestTemplate loginGovOpenIdTemplate(final OAuth2ClientContext clientContext) {
final OAuth2RestTemplate template = new OAuth2RestTemplate(loginGovOpenId(), clientContext);
template.setAccessTokenProvider(accessTokenProvider());
return template;
}
Where my CustomStateKeyGenerator implementation class looks as follows:
public class CustomStateKeyGenerator implements StateKeyGenerator {
// login.gov requires state to be at least 32-characters long
private static int length = 32;
private RandomValueStringGenerator generator = new RandomValueStringGenerator(length);
#Override
public String generateKey(OAuth2ProtectedResourceDetails resource) {
return generator.generate();
}
}

spring-integration-dsl: Make Feed-Flow Work

I'm trying to code a RSS-feed reader with a configured set of RSS-feeds. I thought that a good approach is to solve that by coding a prototype-#Bean and call it with each RSS-feed found in the configuration.
However, I guess that I'm missing a point here as the application launches, but nothing happens. I mean the beans are created as I'd expect, but there is no logging happening in that handle()-method:
#Component
public class HomeServerRunner implements ApplicationRunner {
private static final Logger logger = LoggerFactory.getLogger(HomeServerRunner.class);
#Autowired
private Configuration configuration;
#Autowired
private FeedConfigurator feedConfigurator;
#Override
public void run(ApplicationArguments args) throws Exception {
List<IntegrationFlow> feedFlows = configuration.getRssFeeds()
.entrySet()
.stream()
.peek(entry -> System.out.println(entry.getKey()))
.map(entry -> feedConfigurator.feedFlow(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
// this one appears in the log-file and looks good
logger.info("Flows: " + feedFlows);
}
}
#Configuration
public class FeedConfigurator {
private static final Logger logger = LoggerFactory.getLogger(FeedConfigurator.class);
#Bean
#Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public IntegrationFlow feedFlow(String name, FeedConfiguration configuration) {
return IntegrationFlows
.from(Feed
.inboundAdapter(configuration.getSource(), getElementName(name, "adapter"))
.feedFetcher(new HttpClientFeedFetcher()),
spec -> spec.poller(Pollers.fixedRate(configuration.getInterval())))
.channel(MessageChannels.direct(getElementName(name, "in")))
.enrichHeaders(spec -> spec.header("feedSource", configuration))
.channel(getElementName(name, "handle"))
//
// it would be nice if the following would show something:
//
.handle(m -> logger.debug("Payload: " + m.getPayload()))
.get();
}
private String getElementName(String name, String postfix) {
name = "feedChannel" + StringUtils.capitalize(name);
if (!StringUtils.isEmpty(postfix)) {
name += "." + postfix;
}
return name;
}
}
What's missing here? It seems as if I need to "start" the flows somehow.
Prototype beans need to be "used" somewhere - if you don't have a reference to it anywhere, no instance will be created.
Further, you can't put an IntegrationFlow #Bean in that scope - it generates a bunch of beans internally which won't be in that scope.
See the answer to this question and its follow-up for one technique you can use to create multiple adapters with different properties.
Alternatively, the upcoming 1.2 version of the DSL has a mechanism to register flows dynamically.

Can't use a session ejb in my managed bean cause i get a Null Pointer Exception

First of all I want to say I'm pretty new in programming with ejb and jsf, and I'm trying to complete a project started by a friend of mine.
I'm getting a NullPointerException caused by the invoke of the method utenteSessionBean.CheckUtentebyId(username) of the session bean object called utenteSessionBean, declared inside the managed bean called Neo4jMBean.
I learned that it's not necessary creating and initializing a session bean (as you must do with a normal java object) in managed bean, but it's enough declaring it.
Here is the code of the session bean, which retrieves data from a DB
#Stateless
#LocalBean
public class UtenteSessionBean {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("EnterpriseApplication2-ejbPU");
public boolean CheckUtentebyId(String username){
EntityManager em = emf.createEntityManager();
Query query = em.createNamedQuery("Utente.findByUsername");
query.setParameter("username", username);
List<Utente> Res=query.getResultList();
//completare funzione ctrl+spazio
System.out.println("pre");
System.out.println("pre"+Res.isEmpty());
em.close();
System.out.println("post");
System.out.println("post"+Res.isEmpty());
if(Res.size()>=1)
{
return true;
}
else
{
return false;
}
}
}
Here's the code of the managed bean:
#ManagedBean
#ViewScoped
public class Neo4jMBean {
#EJB
private UtenteSessionBean utenteSessionBean;
static String SERVER_ROOT_URI = "http://localhost:7474/db/data/";
public Neo4jMBean() {
}
public boolean getUser(String username) {
return utenteSessionBean.CheckUtentebyId(username);
}
}
I've searched on StackOverFlow many times a solution for fixing this problem, but I haven't found something that works for me yet.
I fixed it accessing the EJB Components using JNDI.
In few words, if i use an EJB in a managed bean method, i need to add the next lines of code:
InitialContext ic = new InitialContext();
SessionBeanName = (SessionBeanClass) ic.lookup("java:global/NameOfTheApplication/NameOfTheEJBpackage/NameOfTheSessionBean");
It must be surronded by a try-catch statement
Create empty beans.xml file in your WEB-INF folder to enable CDI

Quartz.net and Ninject: how to bind implementation to my job using NInject

I am actually working in an ASP.Net MVC 4 web application where we are using NInject for dependency injection. We are also using UnitOfWork and Repositories based on Entity framework.
We would like to use Quartz.net in our application to start some custom job periodically. I would like that NInject bind automatically the services that we need in our job.
It could be something like this:
public class DispatchingJob : IJob
{
private readonly IDispatchingManagementService _dispatchingManagementService;
public DispatchingJob(IDispatchingManagementService dispatchingManagementService )
{
_dispatchingManagementService = dispatchingManagementService ;
}
public void Execute(IJobExecutionContext context)
{
LogManager.Instance.Info(string.Format("Dispatching job started at: {0}", DateTime.Now));
_dispatchingManagementService.DispatchAtomicChecks();
LogManager.Instance.Info(string.Format("Dispatching job ended at: {0}", DateTime.Now));
}
}
So far, in our NInjectWebCommon binding is configured like this (using request scope):
kernel.Bind<IDispatchingManagementService>().To<DispatchingManagementService>();
Is it possible to inject the correct implementation into our custom job using NInject ? and how to do it ? I have read already few posts on stack overflow, however i need some advises and some example using NInject.
Use a JobFactory in your Quartz schedule, and resolve your job instance there.
So, in your NInject config set up the job (I'm guessing at the correct NInject syntax here)
// Assuming you only have one IJob
kernel.Bind<IJob>().To<DispatchingJob>();
Then, create a JobFactory: [edit: this is a modified version of #BatteryBackupUnit's answer here]
public class NInjectJobFactory : IJobFactory
{
private readonly IResolutionRoot resolutionRoot;
public NinjectJobFactory(IResolutionRoot resolutionRoot)
{
this.resolutionRoot = resolutionRoot;
}
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
// If you have multiple jobs, specify the name as
// bundle.JobDetail.JobType.Name, or pass the type, whatever
// NInject wants..
return (IJob)this.resolutionRoot.Get<IJob>();
}
public void ReturnJob(IJob job)
{
this.resolutionRoot.Release(job);
}
}
Then, when you create the scheduler, assign the JobFactory to it:
private IScheduler GetSchedule(IResolutionRoot root)
{
var schedule = new StdSchedulerFactory().GetScheduler();
schedule.JobFactory = new NInjectJobFactory(root);
return schedule;
}
Quartz will then use the JobFactory to create the job, and NInject will resolve the dependencies for you.
Regarding scoping of the IUnitOfWork, as per a comment of the answer i linked, you can do
// default for web requests
Bind<IUnitOfWork>().To<UnitOfWork>()
.InRequestScope();
// fall back to `InCallScope()` when there's no web request.
Bind<IUnitOfWork>().To<UnitOfWork>()
.When(x => HttpContext.Current == null)
.InCallScope();
There's only one caveat that you should be aware of:
With incorrect usage of async in a web request, you may mistakenly be resolving a IUnitOfWork in a worker thread where HttpContext.Current is null. Now without the fallback binding, this would fail with an exception which would show you that you've done something wrong. With the fallback binding however, the issue may present itself in an obscured way. That is, it may work sometimes, but sometimes not. This is because there will be two (or even more) IUnitOfWork instances for the same request.
To remedy this, we can make the binding more specific. For this, we need some parameter to tell us to use another than InRequestScope(). Have a look at:
public class NonRequestScopedParameter : Ninject.Parameters.IParameter
{
public bool Equals(IParameter other)
{
if (other == null)
{
return false;
}
return other is NonRequestScopedParameter;
}
public object GetValue(IContext context, ITarget target)
{
throw new NotSupportedException("this parameter does not provide a value");
}
public string Name
{
get { return typeof(NonRequestScopedParameter).Name; }
}
// this is very important
public bool ShouldInherit
{
get { return true; }
}
}
now adapt the job factory as follows:
public class NInjectJobFactory : IJobFactory
{
private readonly IResolutionRoot resolutionRoot;
public NinjectJobFactory(IResolutionRoot resolutionRoot)
{
this.resolutionRoot = resolutionRoot;
}
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
return (IJob) this.resolutionRoot.Get(
bundle.JobDetail.JobType,
new NonrequestScopedParameter()); // parameter goes here
}
public void ReturnJob(IJob job)
{
this.resolutionRoot.Release(job);
}
}
and adapt the IUnitOfWork bindings:
Bind<IUnitOfWork>().To<UnitOfWork>()
.InRequestScope();
Bind<IUnitOfWork>().To<UnitOfWork>()
.When(x => x.Parameters.OfType<NonRequestScopedParameter>().Any())
.InCallScope();
This way, if you use async wrong, there'll still be an exception, but IUnitOfWork scoping will still work for quartz tasks.
For any users that could be interested, here is the solution that finally worked for me.
I have made it working doing some adjustment to match my project. Please note that in the method NewJob, I have replaced the call to Kernel.Get by _resolutionRoot.Get.
As you can find here:
public class JobFactory : IJobFactory
{
private readonly IResolutionRoot _resolutionRoot;
public JobFactory(IResolutionRoot resolutionRoot)
{
this._resolutionRoot = resolutionRoot;
}
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
try
{
return (IJob)_resolutionRoot.Get(
bundle.JobDetail.JobType, new NonRequestScopedParameter()); // parameter goes here
}
catch (Exception ex)
{
LogManager.Instance.Info(string.Format("Exception raised in JobFactory"));
}
}
public void ReturnJob(IJob job)
{
}
}
And here is the call schedule my job:
public static void RegisterScheduler(IKernel kernel)
{
try
{
var scheduler = new StdSchedulerFactory().GetScheduler();
scheduler.JobFactory = new JobFactory(kernel);
....
}
}
Thank you very much for your help
Thanks so much for your response. I have implemented something like that and the binding is working :):
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
var resolver = DependencyResolver.Current;
var myJob = (IJob)resolver.GetService(typeof(IJob));
return myJob;
}
As I told before I am using in my project a service and unit of work (based on EF) that are both injected with NInject.
public class DispatchingManagementService : IDispatchingManagementService
{
private readonly IUnitOfWork _unitOfWork;
public DispatchingManagementService(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
}
Please find here how I am binding the implementations:
kernel.Bind<IUnitOfWork>().To<EfUnitOfWork>()
kernel.Bind<IDispatchingManagementService>().To<DispatchingManagementService>();
kernel.Bind<IJob>().To<DispatchingJob>();
To resume, the binding of IUnitOfWork is done for:
- Eevery time a new request is coming to my application ASP.Net MVC: Request scope
- Every time I am running the job: InCallScope
What are the best practices according to the behavior of EF ? I have find information to use CallInScope. Is it possible to tell NInject to get a scope ByRequest everytime a new request is coming to the application, and a InCallScope everytime my job is running ? How to do that ?
Thank you very much for your help

How to find out what open sessions my servlet based application is handling at any given moment

I need to write a servlet that, when called, gets information about a list of the currently opened sessions.
Is there a way to do this?
Implement HttpSessionListener, give it a static Set<HttpSession> property, add the session to it during sessionCreated() method, remove the session from it during sessionDestroyed() method, register the listener as <listener> in web.xml. Now you've a class which has all open sessions in the current JBoss instance collected. Here's a basic example:
public HttpSessionCollector implements HttpSessionListener {
private static final Set<HttpSession> sessions = ConcurrentHashMap.newKeySet();
public void sessionCreated(HttpSessionEvent event) {
sessions.add(event.getSession());
}
public void sessionDestroyed(HttpSessionEvent event) {
sessions.remove(event.getSession());
}
public static Set<HttpSession> getSessions() {
return sessions;
}
}
Then in your servlet just do:
Set<HttpSession> sessions = HttpSessionCollector.getSessions();
If you rather want to store/get it in the application scope so that you can make the Set<HttpSession> non-static, then let the HttpSessionCollector implement ServletContextListener as well and add basically the following methods:
public void contextCreated(ServletContextEvent event) {
event.getServletContext().setAttribute("HttpSessionCollector.instance", this);
}
public static HttpSessionCollector getCurrentInstance(ServletContext context) {
return (HttpSessionCollector) context.getAttribute("HttpSessionCollector.instance");
}
which you can use in Servlet as follows:
HttpSessionCollector collector = HttpSessionCollector.getCurrentInstance(getServletContext());
Set<HttpSession> sessions = collector.getSessions();
Perhaps using a JMX bean is more elegant and needs no code. Just read the value of
data: jboss.web:type=Manager,path=/myapplication,host=localhost" activeSessions

Resources