javax.inject.Current cannot be found - jsf

I am trying to learn JSF using netbeans with glass fish.
Everything is up to date. From the sdk to netbeans. I am following some examples from a book published in 2009.
In out of the examples, the writer has used the #Current annotations and imported javax.inject.Current.
When i try out the code using netbeans, netbeans throws an error. I have added the java EE 7 library but nothing doing.
In your answer(s) 1- Explain why netbeans cannot find the class and 2- Give step by step procedures for adding the class to my project.
Here's the code I'm using.
` package hello;
import java.util.*;
import javax.faces.bean.RequestScoped;
import javax.inject.Named;
import javax.inject.Inject.Current;
#Named
#RequestScoped
public class QuoteRequest {
private String symbol;
#Current
private StockService service;
private Date quoteDate = new Date();
public QuoteRequest() {
}
public String getSymbol() {
return symbol;
}
public void setSymbol(String symbol) {
this.symbol = symbol;
}
public double getStockValue(){
return service.getStockValue(this);
}
public Date getQuoteDate() {
return quoteDate;
}
public void setQuoteDate(Date qouteDate) {
this.quoteDate = qouteDate;
}
}
`

You need to do two things
Use #Inject annotation from javax.inject package instead of #Current annotation as the book says.
Make sure you have an empty beans.xml file in your WEB-INF folder. This file is important to treat your beans as CDI beans.

Related

Injecting a different bean during local development with Quarkus

With Spring and Micronaut, there are very concise ways to inject a different bean depending on what environment/profile an application is running in. I'm trying to do the same with Quarkus.
I've read this post: https://quarkus.io/blog/quarkus-dependency-injection/. And the process is alluded to in this StackOverflow post: How can I override a CDI bean in Quarkus for testing?. That last post says, "create bean in test directory".
My problem is slightly different. I'd like to inject a bean when in "development". In production, I'd like the default bean injected. From the docs, I can't see a way to have the app make this distinction.
If I have a default class like this:
#DefaultBean
#ApplicationScoped
class ProdProvider : SomeProvider {}
And I want to override it like this:
#Alternative
#Priority(1)
class DevProvider : SomeProvider {}
How can I make this happen only in dev mode?
In one case, I have a credential provider class that sets up Google's PubSub emulator while in local development. In production, I use a class that implements the same interface, but a real credential provider. The particular case that led me to asking this question, though is a a class that implements one method:
#ApplicationScoped
class VaultLoginJwtProvider : LoginJwtProvider {
#ConfigProperty(name = "vault.tokenPath")
private val jwtPath: String? = null
companion object {
val logger: Logger = LoggerFactory.getLogger("VaultTokenProvider")
}
override fun getLoginJwt(): Optional<String> {
logger.info("Using Vault Login JWT")
return try {
Optional.of(String(Files.readAllBytes(Paths.get(jwtPath))).trim { it <= ' ' })
} catch (e: Exception) {
logger.error("Could not read vault token at $jwtPath")
logger.error(e.printStackTrace().toString())
Optional.empty()
}
}
}
That class is injected into another class via constructor injection:
#Singleton
class JwtServiceImpl(
#RestClient val vaultClient: VaultClient,
#Inject val loginJwtProvider: LoginJwtProvider
) {
private var serviceJwt: String? = null
companion object {
val logger: Logger = LoggerFactory.getLogger("JwtServiceImpl")
}
private fun getLoginToken(): String? {
val vaultLogin = VaultLogin(
role = "user-service",
jwt = loginJwtProvider.getLoginJwt().get()
)
val loginResponse = vaultClient.login(vaultLogin)
return loginResponse.auth.clientToken
}
}
I'd like to inject more of a "mock" class while in development that just returns a static string. I could use ProfileManager.getActiveProfile(), but that has me mixing development concerns into my logic. And I don't feel that that has any place in my compiled production code.
This is possible in Micronaut by using the annotation #Requires(env = ["dev", "test"]). I did briefly look at using #Produces but the Oracle EE docs seemed a little bit difficult for me to grasp. If that's the solution, I'll dig in.
In case anybody else comes across this, this is how to do it: https://quarkus.io/guides/cdi-reference#enabling-beans-for-quarkus-build-profile
For example:
import javax.enterprise.inject.Produces;
import com.oi1p.common.EmailSender;
import com.oi1p.common.ErrorEmailSender;
import com.oi1p.common.LogOnlyEmailSender;
import io.quarkus.arc.DefaultBean;
import io.quarkus.arc.profile.IfBuildProfile;
#ApplicationScoped
public class Producers {
#Produces
#IfBuildProfile("dev")
public EmailSender logOnlyEmailSender() {
return new LogOnlyEmailSender();
}
#Produces
#DefaultBean
public EmailSender errorEmailSender() {
// TODO: implement a real email sender. This one explodes when poked.
return new ErrorEmailSender();
}
}
My solution is to create the final bean on my own inside a #javax.ws.rs.ext.Provider. Not as elegant as Micronaut #Requires, but well, it works.
Note that instance of SomeProvider is not a "bean", you have to care for the lifecycle on your own (dependency injection, PostConstruct, no PreDestroy, ...).
org.acme.SomeProvider.java
package org.acme;
import javax.enterprise.context.ApplicationScoped;
public interface SomeProvider {
void providerMethod();
#ApplicationScoped
class ProdProviderRequirement {
void foo() {}
}
class ProdProvider implements SomeProvider {
private final ProdProviderRequirement prodProviderRequirement;
ProdProvider(final ProdProviderRequirement prodProviderRequirement) {
this.prodProviderRequirement = prodProviderRequirement;
}
#Override
public void providerMethod() {
prodProviderRequirement.foo();
}
}
class DevProvider implements SomeProvider {
#Override
public void providerMethod() {}
}
}
org.acme.SomeProviderFactory.java
package org.acme;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;
import javax.inject.Inject;
import javax.ws.rs.ext.Provider;
import org.acme.SomeProvider.DevProvider;
import org.acme.SomeProvider.ProdProvider;
import org.acme.SomeProvider.ProdProviderRequirement;
#Provider
class SomeProviderFactory {
SomeProvider someProvider;
#Inject
SomeProviderFactory(final ProdProviderRequirement prodProviderRequirement) {
final var someCondition = true;
someProvider = someCondition ? new DevProvider() : new ProdProvider(prodProviderRequirement);
}
#Produces
#ApplicationScoped
SomeProvider someProvider() {
return someProvider;
}
}

JSF update managed bean with ServletContext listener for testing

In a JSF 2.2 application, I want to build a war file for testing with Selenium. In that webtest.war, I want to replace a central class, called the NodeCache, with a mock version, called the WebtestNodeCache, to keep the database and other external dependencies out of the tests.
NodeCache is a managed bean:
#javax.faces.bean.ManagedBean(name = NodeCache.INSTANCE)
#javax.faces.bean.ApplicationScoped
public class NodeCache {
public static final String INSTANE = "nodecache";
// ...
}
To sneak in WebtestNodeCache, I use a ServletContextListener like this:
public class WebtestContextListener implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent event) {
WebtestNodeCache nodeCache = new WebtestNodeCache();
ServletContext context = event.getServletContext();
context.setAttribute(NodeCache.INSTANCE, nodeCache);
}
#Override
public void contextDestroyed(ServletContextEvent sce) {}
}
In normal builds, WebtestContextListener and WebtestNodeCache are excluded from the war file, in test builds, they are included.
This seems to work: when I log in, I get dummy nodes from the WebtestNodeCache.
Is this a reliable way to replace a bean in application context or did I just get lucky?
Is there a better way to sneak in test dummies?
Using both an #ManagedBean annotation and a Listener to replace the object did not work. The code was always using the unmocked production code managed bean.
Defining a new #ManagedBean with the same name is an error and prevents deployment.
I ended up with this:
Put the #ManagedBean annotation with the same name on both the real bean and its mock.
When building, only include the mocks when building the webtest.war, but not in the regular build.
When building, have the build script (Gradle in my case) copy and filter the sources, looking for a special comment behind the #ManagedBean declaration in the production code and taking out these lines to remove the #ManagedBean declaration on the production code so that only the ones in the mock remains.
So the original NodeCache looks like this now:
#javax.faces.bean.ManagedBean(name = NodeCache.INSTANCE) // webtest:remove
#javax.faces.bean.ApplicationScoped // webtest:remove
public class NodeCache {
public static final String INSTANE = "nodecache";
// ...
}
and the mocked version has the same annotations, just without the comment:
#javax.faces.bean.ManagedBean(name = NodeCache.INSTANCE)
#javax.faces.bean.ApplicationScoped
public class WebtestNodeCache extends NodeCache {
// ...
}
Here is the relevant part of the Gradle build script:
boolean isWebtest = false
gradle.taskGraph.whenReady { taskGraph ->
isWebtest = taskGraph.hasTask(compileWebtestWarJava);
}
task copySrc(type: Copy) {
from "src"
into "${buildDir}/src"
outputs.upToDateWhen {
// Always execute this task so that resources do or don't get filtered
// when switching between normal war file and webtests.
false
}
filter { String line ->
isWebtest && line.contains("webtest:remove") ? null : line;
}
}
This solves the problem for me. Hope someone else finds it useful.

How to override class DefaultScreenNameValidator in liferay 7?

I am trying to override a class DefaultScreenNameValidator that implements ScreenNameValidator interface. For this , I copied the class and put it into another module. One change that I made is in annotation that is as follows:-
#Component(
property = {
"service.ranking:Integer=500"
}
)
I got a successful build using this. But when I tried to deploy the project, I got error as java.lang.NoClassDefFoundError: com/liferay/portal/kernel/security/auth/ScreenNameValidator.Can you suggest me how to eradicate this error. Thanx in advance..
I'm wondering, wouldn't it be better to instead create a module that also implements the ScreenNameValidator interface, and define your custom logic in there? Then you can just simply tell Liferay to use that validator instead of the DefaultScreenNameValidator.
For example, a minimalistic implementation:
import com.liferay.portal.kernel.security.auth.ScreenNameValidator;
import org.osgi.service.component.annotations.Component;
#Component(
immediate = true,
service = ScreenNameValidator.class
)
public class CustomScreenNameValidator implements ScreenNameValidator {
#Override
public boolean validate(long companyId, String screenName) {
// Your custom logic
}
}
make sure you have the dependency to portal-kernel in the build.gradle
dependencies {
compile 'com.liferay.portal:com.liferay.portal.kernel:2.0.0'
I made a screenNameValidator using blade-cli you can see the projet at https://github.com/bruinen/liferay-blade-samples/tree/master/liferay-workspace/modules/blade.screenname.validator
import com.liferay.portal.kernel.security.auth.ScreenNameValidator;
import org.osgi.service.component.annotations.Component;
import java.util.Locale;
#Component(
immediate = true,
property = {"service.ranking:Integer=100"},
service = ScreenNameValidator.class
)
public class CustomScreenNameValidator implements ScreenNameValidator {
#Override
public String getAUIValidatorJS() {
return "function(val) {return !(val.indexOf(\"admin\") !==-1)}";
}
#Override
public String getDescription(Locale locale) {
return "The screenName contains reserved words";
}
#Override
public boolean validate(long companyId, String screenName) {
return !screenName.contains("admin");
}
}

Groovy unable to access private property of super class using `#`

There is a third party java class in a library. Trying to extend that class in a Groovy Class. I would like to access that private property.
The problem is that it says
No such field: firstName for class: test2.Superuser
I am sure there must be a way to access the same and manipulate the property value using groovy.
Some posts suggests to use # before property name in order to access private property. But no luck.
Here is the sample code snippets.
User.java (a third party class of a library)
package test;
class User {
private String firstName;
private String name() {
firstName;
}
}
SuperUser.groovy (The one I am trying)
package test2
import test.User
class SuperUser extends User {
public static void main(String[] args) {
def suser = new SuperUser()
suser.#firstName = "John"
println suser.name()
}
}
Any help is appreciated.
Using below versions:
groovy : 1.8.0
jdk : 1.7.0
Java classes aren't able to access all of these private fields, properties and methods. It is only the other groovy scripts that are able to access it. The example below will demonstrate the same.
You should try to create both class file name as .groovy instead .java
User.groovy :
class User {
private String firstName;
private String name() {
firstName;
}
}
UserTest.groovy :-
class UserTest {
public static void main(String[] args) {
User user = new User();
user.#firstName = "John"
println user.name()
}
}
Output :- John
It's working fine with Java 8 and groovy-all-2.4.3
Note:- Follow this link for more details
Edited :- If you don't want to change super class because of third party code, you should try using java reflection to access private property of a class.
User.java is a Java class and not a Groovy class, so those variables are still private (unlike Groovy Variables which are always public to other Groovy classes).
So in the example above, unless the Java class includes some getters and setters, you will not be able to modify it's private members.
Maybe I'm late, but with your Java and Groovy version you can do the follow using meta programming:
package test2
import test.User
class SuperUser extends User {
public static void main(String[] args) {
def suser = new SuperUser()
User.metaClass.setProperty(suser,'firstName','John')
println User.metaClass.getMetaMethod('name',null).invoke(suser,null)
}
}
Or as other suggest in the traditional java reflection way:
package test2
import test.User
class SuperUser extends User {
public static void main(String[] args) {
def suser = new SuperUser()
def firstNameField = SuperUser.superclass.getDeclaredField('firstName')
firstNameField.setAccessible(true)
firstNameField.set(suser,"John")
def nameMethod = SuperUser.superclass.getDeclaredMethod('name')
nameMethod.setAccessible(true)
println nameMethod.invoke(suser,null)
}
}

Accessing static field in annotation

Im trying use a Java annotation in a Groovy class but have trouble to set a static field of a java class as a parameter:
The Annotation: Id.java
package x.y.annotations;
import java.lang.annotation.ElementType;
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.FIELD)
public #interface Id {
public Class<Adapter> adapter();
public Class<Object> targetType();
public String targetAttribute();
public String onDelete();
}
The java class with the static fields: XPerson.java
package x.y.static.domain;
public class XPerson {
public static String ID;
}
And the groovy class, where the problem occurs: Person.groovy
package x.y.domain
import x.y.annotations.Id
import x.y.static.domain.XPerson
class Person {
#Id(adapter = Adapter, targetType = XPerson, targetAttribute = XPerson.ID, onDelete = "delete")
long id
}
Eclipse marks the "targetAttribute = XPerson.ID" part with:
Groovy:expected 'x.y.domain.XPerson.ID' to be an inline constant of type java.lang.String not a property expression in #x.y.annotations.Id
I also tried things like "XPerson.#ID" or defining a getter for the ID field, but nothing helped.
Any hints would be great.
Regards,
michael
I have found a related issue in the Groovy JIRA. It is a bug. Should work. See https://issues.apache.org/jira/browse/GROOVY-3278
Annotation values may only be compile-time constant expressions. Making the field final is an option. (With the caveat that the field can't be initialized in a static initializer/etc. as the snippet implies.)

Resources