I have a cacheBean called PCConfig in which I want to store references to databases, so I can access them in other Java methods.
Here is the relevant part of my cacheBean:
package com.scoular.cache;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Vector;
import org.openntf.domino.utils.Factory;
import org.openntf.domino.xsp.XspOpenLogUtil;
import org.openntf.domino.Database;
import org.openntf.domino.Session;
import org.openntf.domino.View;
import org.openntf.domino.ViewEntry;
import org.openntf.domino.ViewNavigator;
public class PCConfig implements Serializable {
private static final long serialVersionUID = 1L;
private static Database PCDataDB;
// #SuppressWarnings("unchecked")
private void initConfigData() {
try {
loadStatus();
loadGeoLocations();
loadModels();
loadDatabases();
} catch (Exception e) {
XspOpenLogUtil.logError(e);
}
}
public PCConfig() {
initConfigData();
}
//Getters
public static Database getPCDataDB() {
return PCDataDB;
}
public static void setPCDataDB(Database dataDB) {
PCDataDB = dataDB;
}
public static void loadDatabases() {
loadPCDataDB();
}
public static void loadPCDataDB() {
Session session = Factory.getSession();
PCConfig.PCDataDB = session.getDatabase(thisDB.getServer(),"scoApps\\PC\\PCData.nsf", false);
}
}
}
In a different java class I import the PCConfig class and try to use this method getPCDataDB(). I have also tried PCConfig.PCDataDB.
I always get the error null pointer exception.
What am I doing wrong?
public void loadByUnid(String unid) {
try {
Document doc = PCConfig.getPCDataDB().getDocumentByUNID(unid);
if (null == doc) {
System.out.println("Document not found");
} else {
loadValues(doc);
}
} catch (Exception e) {
XspOpenLogUtil.logError(e);
}
}
You call the static method getPCDataDB(). As it is static you don't need to instantiate the class. But, your private field Database PCDataDB is not initialized at this point. This only happens if you instantiate the class. That's why you get the null pointer exception.
I guess PCConfig is a managed bean. It would get instantiated automatically if you call a non-static method in SSJS. So, remove all static in your class and it should work. If you want to use the class in Java then instantiate the class before calling getPCDataDB():
PCConfig pcConfig = new PCConfig();
Document doc = pcConfig.getPCDataDB().getDocumentByUNID(unid);
It is not recommended to keep Domino objects as class fields (like your Database PCDataDB) as they are not serializable. They might get recycled over the time especially if the class object resides in a long life scope like application scope. It is better to keep the data itself in fields or in your case database's server name and path so that you can open the database again when you need it.
BTW private Database PCDataDB should be private Database pCDataDB. The convention is that only class names and interfaces start with a capital letter.
As Knut says, storing the database in your static class won't work. Normally you would need to store the server and the database path as separate variables. But since you're using the OpenNTF Domino API, you can take advantage of Database.getApiPath() , which returns a "metaReplicaID" - a combination of servername and replica ID. You can store that and you have a direct reference to where the database resides. You can then use session.getDatabase(metaReplicaID) to retrieve the database when required.
Related
I am trying to define some different mocked behaviours when a method is called with different parameters. Unfortunately, I find that the second time I try to mock the given method on a (mocked) class, it runs the actual method, causing an exception because the matchers are not valid parameters. Anyone know how I can prevent this?
manager = PowerMockito.mock(Manager.class);
try {
PowerMockito.whenNew(Manager.class).withArguments(anyString(), anyString())
.thenReturn(manager);
} catch (Exception e) {
e.printStackTrace();
}
FindAuthorityDescriptionRequestImpl validFindAuthorityDescription = mock(FindAuthorityDescriptionRequestImpl.class);
PowerMockito.when(manager.createFindAuthorityDescriptionRequest(anyString(), anyString())).thenCallRealMethod();
PowerMockito.when(manager.createFindAuthorityDescriptionRequest(Matchers.eq(VALID_IK),
Matchers.eq(VALID_CATEGORY_NAME))).thenReturn(validFindAuthorityDescription);
PowerMockito.when(manager.processRequest(Matchers.any(FindAuthorityDescriptionRequest.class)))
.thenThrow(ManagerException.class);
PowerMockito.when(manager.processRequest(Matchers.eq(validFindAuthorityDescription)))
.thenReturn(generateValidAuthorityDescriptionResponse());
The following code is a working example based on your mock setup (I've added dummy classes to make it runnable).
The code also contains asserts to verify that the mocked methods return expected values. Also, the real method createFindAuthorityDescriptionRequest is only called once.
Note: This was tested with `powermock 2.0.7` and `mockito 2.21.0`.
If issues persist, I'd suggest checking if the real method is not additionally called from somewhere else in your program (other than the code quoted in your problem statement).
package com.example.stack;
import org.junit.Test;
import org.junit.function.ThrowingRunnable;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;
import static org.mockito.ArgumentMatchers.*;
import static org.powermock.api.mockito.PowerMockito.mock;
#RunWith(PowerMockRunner.class)
#PrepareForTest(fullyQualifiedNames = "com.example.stack.*")
public class StackApplicationTests {
private static final String VALID_IK = "IK";
private static final String VALID_CATEGORY_NAME = "CATEGORY_NAME";
private static final Object VALID_RESPONSE = "RESPONSE";
#Test
public void test() {
Manager manager = mock(Manager.class);
try {
PowerMockito.whenNew(Manager.class).withArguments(anyString(), anyString())
.thenReturn(manager);
} catch (Exception e) {
e.printStackTrace();
}
FindAuthorityDescriptionRequestImpl validFindAuthorityDescription = mock(FindAuthorityDescriptionRequestImpl.class);
PowerMockito.when(manager.createFindAuthorityDescriptionRequest(anyString(), anyString())).thenCallRealMethod();
PowerMockito.when(manager.createFindAuthorityDescriptionRequest(eq(VALID_IK), eq(VALID_CATEGORY_NAME)))
.thenReturn(validFindAuthorityDescription);
PowerMockito.when(manager.processRequest(any(FindAuthorityDescriptionRequest.class)))
.thenThrow(ManagerException.class);
PowerMockito.when(manager.processRequest(eq(validFindAuthorityDescription)))
.thenReturn(VALID_RESPONSE);
// verify that the mock returns expected results
assertEquals(Manager.REAL_RESULT, manager.createFindAuthorityDescriptionRequest("any", "any"));
assertEquals(validFindAuthorityDescription, manager.createFindAuthorityDescriptionRequest("IK", "CATEGORY_NAME"));
assertThrows(ManagerException.class, new ThrowingRunnable(){
#Override
public void run( ) {
manager.processRequest(new FindAuthorityDescriptionRequestImpl());
}
});
assertEquals(VALID_RESPONSE, manager.processRequest(validFindAuthorityDescription));
}
}
interface FindAuthorityDescriptionRequest {}
class FindAuthorityDescriptionRequestImpl implements FindAuthorityDescriptionRequest {}
class ManagerException extends RuntimeException {}
class Manager {
public static FindAuthorityDescriptionRequestImpl REAL_RESULT = new FindAuthorityDescriptionRequestImpl();
public Manager(String s1, String s2) {}
public FindAuthorityDescriptionRequest createFindAuthorityDescriptionRequest(String ik, String category) {
return REAL_RESULT;
}
public Object processRequest(FindAuthorityDescriptionRequest request) {
return null;
}
}
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;
}
}
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");
}
}
I have a web app that uses JSF pages and entity classes, where a user has to authenticate to be able to publish some exercises to his students.
In the entity class, a "user" object has:
id(int), login(string), password(string) and type(string)
In my "users" controller bean, i have a method to see if the user already exists in database. And that process goes well. All is working fine. So, i know for sure that a "user" object is instantiated with the correct data.
I have another controller that is used in another JSF page where the user can publish an exercise.
In the entity class, an "exercise" object has:
id(int), userID(int)(foreign key to ID on users), description(string), etc.
When i'm preparing the "exercise" object in the "exercises" controller, to save to database, i need to have access to the "user" object in the other controller to set the userID. And this is the reason of my headache! Because the userID allways sets to null !!!
I've tryed with #Named and #Inject(recommended), also with #Managedbean and #ManagedProperty(wich they say will be deprecated) ... Tryed with single and mixed combinations of #RequestScoped and #SessionScoped ... Tryed to instantiated the "user" object inside a #PostConstruct method in "exercises" controller... Have already read many examples on how to do it, but none of it works!
I know this is a very basic problem i'm having! And it only consists on how to pass an object from one controller to another! Still no SUCCESS, after TWO days of experimenting! This is driving me crazy!
Please HELP!:
"users" Controller
package controlers;
import beans.UtilizadoresFacade;
import entities.Utilizadores;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.EJB;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
#Named("utilizadoresController")
#RequestScoped
public class UtilizadoresController implements Serializable {
#EJB
UtilizadoresFacade ejbFacade;
Utilizadores utilizador = new Utilizadores(); //The one i want to pass to the other controller
List<Utilizadores> utilizadores = new ArrayList();
public Utilizadores getUtilizador() {
return utilizador;
}
public void setUtilizador(Utilizadores utilizador) {
this.utilizador = utilizador;
}
public List<Utilizadores> getUtilizadores() {
return utilizadores = (List<Utilizadores>)ejbFacade.consultarUtilizadores();
}
public String verificarUtilizador() { // method to verify the user in database by name and password
utilizadores = (List<Utilizadores>)ejbFacade.consultarUtilizador(utilizador.getNome(), utilizador.getSenha());
if(utilizadores.isEmpty())
return "index.xhtml";
else if(utilizadores.get(0).getTipo().equals("normal")) {
utilizador.setId(utilizadores.get(0).getId()); // Here is where i save the ID to "user" object
return "normal.xhtml";
}
else {
utilizador.setId(utilizadores.get(0).getId());
return "administrador.xhtml";
}
}
public String criarUtilizador(){ // this method is to add new user to database and it works fine.
ejbFacade.adicionarUtilizador(utilizador);
if(utilizador.getTipo().equals("normal"))
return "normal.xhtml";
else
return "administrador.xhtml";
}
}
"exercises" controller
package controlers;
import beans.ExerciciosFacade;
import entities.Exercicios;
import entities.Ucs;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.EJB;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;
#Named("exerciciosController")
#RequestScoped
public class ExerciciosController implements Serializable {
#EJB
ExerciciosFacade ejbFacade;
#Inject
UtilizadoresController utilizadoresController;
Ucs cadeira = new Ucs(); //this is a discipline
Exercicios exercicio = new Exercicios();
List<Exercicios> exercicios = new ArrayList();
public List<Exercicios> getExercicios(){
return exercicios = (List<Exercicios>)ejbFacade.consultarExercicios();
}
public String criarExercicio(){ // Method to add an exercise to database
exercicio.setUcid(cadeira); // Sets de discipline ID to "exercise" object (another foreign key) and works well because this value comes from a form in JSF page
exercicio.setUtilizadorid(utilizadoresController.getUtilizador()); // This is where i try to set de user ID to "exercise" object
ejbFacade.adicionarExercicio(exercicio);
return "normal.xhtml";
}
public Exercicios getExercicio() {
return exercicio;
}
public void setExercicio(Exercicios exercicio) {
this.exercicio = exercicio;
}
public Ucs getCadeira() {
return cadeira;
}
public void setCadeira(Ucs cadeira) {
this.cadeira = cadeira;
}
}
I think the "users" controller should be #SessionScoped because i'll be needing the user data while he is navigating through the pages, but i've used #RequestScoped also so there won't be more conflicts i can't control !!!
One more thing: I'm working with Netbeans 8.1 and java DB also from Netbeans.
Hope i'm not forgetting anything!
Many thanks in advance.
I extract some lines of code from my project.
Here is the class for keeping User session
SessionPreferences.java
#ManagedBean(name = "sessionPreferences")
#SessionScoped
public class SessionPreferences implements Serializable {
public static User getLoggedInUser() {
try {
HttpSession session = (HttpSession) FacesContext.getCurrentInstance()
.getExternalContext().getSession(false);
User authenticatedUser = (User) session.getAttribute("username");
return authenticatedUser;
} catch (Throwable e) {
log.error("Error getting logged in user", e);
return null;
}
}
}
And the login validation
public String validateUsernamePassword() {
CryptWithMD5 clss = new CryptWithMD5();
String md5Pwd = clss.cryptWithMD5(pwd);
boolean valid = DBConnection.validate(user, md5Pwd);
if (valid) {
HttpSession session = SessionBean.getSession();
session.setAttribute("username", user);
return "index";
} else {
FacesContext.getCurrentInstance().addMessage(
null,
new FacesMessage(FacesMessage.SEVERITY_WARN,
"Incorrect Username and Passowrd",
"Please enter correct username and Password"));
return "login";
}
}
From now on, I can get User object by method
SessionPreferences.getLoggedInUser()
I use an xe:objectData as a datasource for a xp:dataTable. objectData1 uses some Java code to retrieve all documents from a view that match a key ( username ). The Java code looks like this:
package com.isatweb.cois;
import static com.ibm.xsp.extlib.util.ExtLibUtil.getCurrentDatabase;
import static com.ibm.xsp.extlib.util.ExtLibUtil.getCurrentSession;
import java.io.Serializable;
import lotus.domino.Database;
import lotus.domino.Name;
import lotus.domino.Session;
import lotus.domino.View;
import lotus.domino.ViewEntryCollection;
public class ObjectDataVisits implements Serializable {
private static final long serialVersionUID = 1L;
ViewEntryCollection vec = null;
public ObjectDataVisits(){
try {
this.update();
} catch (Exception e) {
System.out.print(e);
}
}
public void update() {
try {
Database _db = getCurrentDatabase();
Session _session = getCurrentSession();
Name nam = _session.createName(_session.getEffectiveUserName());
String username = nam.getAbbreviated().replace(" ", "#").replace("/", "#").toUpperCase();
View view = _db.getView("vw_visit_open");
this.vec = view.getAllEntriesByKey(username);
} catch (Exception e) {
System.out.print(e);
}
}
public ViewEntryCollection getVisits(){
return this.vec;
}
}
The XPage has the following code
When I first load the page, the data is read from the wiew and the dataTable displays the NoteIDs of all matching documents.
When I refresh the page using the button, I get an "Object has been removed or recycled" error.
Can anyone pls. show me what I'm doing wrong? ( and perhaps, how to do it right )
The problem is, that Notes objects are not serializable. During the partial refresh the getVisits() method is executed before the update() method. The ViewEntryCollection is a references to a view, and this view is already recycled.
If you just want to store some note id's then you could store them in a Vector instead. Otherwise you have to call your update() method in your getVisits() method everytime.