I wrote a managed bean with post construct method (using #PostContruct), but the method is not being called. I'm using liferay liferay-portal-6.1.2-ce-ga3 with Jboss 7.1.1, and Icefaces 3.0. Can someone help me figure this out?
#SessionScoped
#ManagedBean
public class DetalleVaPortletBean extends BackingPortletUI {
private static final long serialVersionUID = -7127465434575796794L;
public DetalleVaPortletBean() {
try {
System.out.println(this);
} catch (Exception e) {
error(e);
}
}
#PostConstruct
public void postConstruct(){
adicionarPortletPrincipal();
}
}
First of all, enshure that your DetalleVaPortletBean object really is constructed by examin the console output and locate the output from
System.out.println(this);
It might be helpul with some more printouts in the constructor, e.g. System.out.println("DetalleVaPortletBean CTOR");
Related
I am trying to add a advice in my application so that the onEnter and onExit gets called when a method CassandraFunctions.loadObjectByKey is invoked during execution flow. I used below code to register a advice.
protected void instrument(boolean t) {
Instrumentation instrument = null;
// Get loader initialized in premain class
try {
Class<?> c = Class.forName("my.loader.InstrumentLoader");
java.lang.reflect.Method m = c.getMethod("getInstrument");
instrument = (Instrumentation) m.invoke(null);
} catch (Exception e) {
e.printStackTrace();
}
if(instrument == null) {
return;
}
// Add an advice
String clzName = CassandraFunctionsAdvice.class.getName();
new AgentBuilder.Default()
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
.type(ElementMatchers.named("my.functions.CassandraFunctions"))
.transform(
new AgentBuilder.Transformer.ForAdvice()
.include(Class.class.getClassLoader())
.advice(ElementMatchers.named("loadObjectByKey"), clzName))
.installOn(instrument);
}
And the advice class looks like below:
public class CassandraFunctionsAdvice {
#Advice.OnMethodEnter
public static void onEnter(#Advice.Argument(0) String key) {
String debugText = "OnMethodEnter|loadObjectByKey|key=" + key;
System.out.println(debugText);
}
#Advice.OnMethodExit
public static void onExit(#Advice.Thrown Throwable throwable) {
String debugText = "OnMethodExit|loadObjectByKey";
System.out.println(debugText);
}
}
The class that is being instrumented looks like below:
public class CassandraFunctions {
public static Object loadObjectByKey(String key) {
....
return object;
}
}
The instrumented class my.functions.CassandraFunctions is loaded much before the function loadObjectByKey is called on a user request. I am not sure what is missing and why the advice is not getting invoked.
I have already answered your question on the GitHub issue:
The advice code is just a template. The private field is not visible to the code once it is inlined by Byte Buddy.
The question you need to ask yourself is: Could I copy-paste this code to the target class and would it still compile? If no, then you need to change your advice. If you want to manage shared state, you would need to move it to a class that is accessible to the class loader(s) in question and inject it into an appropriate location.
I am using google-guice since a couple of days, and I am getting more and more impressed.
I created a MemberInjector to easily integrate the logging framework SLF4J, just with a additional annotation. That means instead of using always the long term:
private static final Logger LOG = LoggerFactory.getLogger(MyClass.class);
I am now just using:
#Log
Logger LOG;
This is really great, BUT:
I am also using a method-injection as a kind of starter function like this in the same class, AND if I access to the LOG instance there, it causes a NPE! Because it is not injected yet.
#Inject
public void start() {
//And here is the problem...
LOG.info("in start") //causes NPE, cause LOG is not injected yet
}
If I use the LOG instance in another (non-injected) method it works perfectly,.
Is there a way to change the injection order or is it possible to tell guice to inject the MemberInjector earlier? Cause I really would like to use the logging also in the method-injection part.
Thank for any hint.
One solution I found was to create just a additional listener that looks for a defined method like ("init" or "start") and just calls it after creation and injection of members.
See in module configuration:
#Override
protected void configure() {
bindListener(Matchers.any(), new InitMethodTypeListener());
//...
InitMethodTypeListener:
public class InitMethodTypeListener implements TypeListener {
private static final Logger log = LoggerFactory.getLogger(InitMethodTypeListener.class);
#SuppressWarnings("rawtypes")
static class InitInvoker implements InjectionListener {
#Override
public void afterInjection(final Object injectee) {
try {
log.info("Invoke init() from Class: {}", injectee.getClass().getName());
injectee.getClass().getMethod("init").invoke(injectee);
} catch (final Exception e) {
log.error(e.getMessage(), e);
}
}
public static final InitInvoker INSTANCE = new InitInvoker();
}
#SuppressWarnings("unchecked")
#Override
public <I> void hear(final TypeLiteral<I> type, final TypeEncounter<I> encounter) {
try {
if (type.getRawType().getMethod("init") != null) {
encounter.register(InitInvoker.INSTANCE);
}
} catch (final NoSuchMethodException | SecurityException e) {
// do nothing here, if not init-method found - no call
}
}
}
Maybe it not the straight forward way but it works. And so I am sure all members are injected well when the init-method is called.
With this implementation all objects that are under guice control their "init"-method will be called automatically after object creation and injection.
I am trying to automate the construction of some objects in java.
To do this, I have these sample classes:
class TestInjected extends CommonAncestor {
TestInjected() {
System.out.println("I am Test Injected");
}
void exist() {
System.out.println("Hey there, I exist");
}
}
class CommonAncestor {
CommonAncestor() {
super();
init();
}
void init() {
try {
Field f = this.getClass().getDeclaredField("x");
f.set(this, f.getType().newInstance());
} catch (NoSuchFieldException e) {
} catch (IllegalAccessException e) {
} catch (InstantiationException e) {
}
}
}
public class TestInjection extends CommonAncestor{
TestInjected x;
private TestInjected y;
private TestInjected getY() {
if (y == null) {
y = new TestInjected();
}
return y;
}
public TestInjection() {
super();
}
public void test() {
x.exist();
}
public void test2() {
getY().exist();
}
}
And I also have a testing class:
public class TestInjectionTest {
#Test
public void test1() {
TestInjection t = new TestInjection();
t.test();
t.test2();
}
}
What I am doing here is, on constructor, I check for the Field x, and I initialize it via reflection. This way, I make sure that whenever a method is called, like in this case, test(), Field x has already been initialized, and therefor, it works.
The second approach, is to force programmers to use a getter, in this case, for Field y, where this getter method makes sure to initialize the object.
However, I am wondering, if hava has any way to execute reflection, when a variable is accessed. Let's say, instead of having to execute reflection code on constructor, if somehow, that code could be executed whenever "x" is required.
i.e:
x.exist()
--> check x is getting called, initialize it, and then call exist()
Any reflection method, or any library, that gives me this?
I can't really understand what problem you are trying to solve, but I'm sure there is a better solution. Work with the platform, not against it. Having said that the answer is no in the general case. You could run something that rewrites the byte codes (essentially adding a getter behind the scenes) but you can't intercept field accesses out of the box.
Make the fields private and expose them with methods if you need to initialize them. Or do it in the constructor.
EDIT: based on your comments I think what you are really looking for is dependency injection. Take a look at CDI (https://docs.oracle.com/javaee/6/tutorial/doc/giwhl.html) or Spring (https://spring.io) or Guice (https://github.com/google/guice).
A bit of newbie on Webservices, but here's a tricky one I'm struggling with finding a better way to implement. See code below: instead of having to invoke the setClientIPAddress method on each webservice method, is there a way of doing this just once ?
i.e. I tried the following:
// initialisation block
{
WSBean wsBean = new WSBean();
wsBean.setClientIPAddress(getClientIPAdd);
}
this compiles ok but I get a runtime error. Webservice class doesn't seem to like the initialisation block.
#javax.jws.WebService(targetNamespace = "http://baseentity.com/", serviceName = "WSBeanService", portName = "WSBeanPort", wsdlLocation = "WEB-INF/wsdl/WSBeanService.wsdl")
public class WSBeanDelegate {
WSBean wsBean = new WSBean();
public String getBaseInfoList(String baseID) {
wsBean.setClientIPAddress(getClientIPAdd); //
return wsBean.getBaseInfoList(transactionID);
}
public String getBaseEntityInfo(String entityID) {
wsBean.setClientIPAddress(getClientIPAdd);
return wsBean.getBaseEntityInfo(entityID);
}
#WebMethod
private String getClientIPAdd()
{
MessageContext mc = this.wsContext.getMessageContext();
HttpServletRequest req = (HttpServletRequest)mc.get("javax.xml.ws.servlet.request");
return req.getRemoteAddr();
}
I've tried using #PostContruct, as shown below:
#PostContruct
private void init()
{
wsBean.setClientIPAddress(getClientIPAdd);
}
but i get the following error: "illegalaccessexception with modifiers private".
However, declaring the method as public also requires defining the same method in the bean/wsdl file, which is not i want do do. Any suggestions on how to better this code?
Thanks in advance.
Try:
#PostContruct
#javax.jws.WebMethod(exclude=true)
public void init()
{
wsBean.setClientIPAddress(getClientIPAdd);
}
According this article, I've implemented #ManagedProperty(value="#{settings}") to my backing bean:
BEAN Bde.java:
#Entity
#Table(name="bdeDATA")
#ViewScoped
#ManagedBean(name="BDE")
public class Bde implements Serializable
{
/**/
private static final long serialVersionUID = -705775502999920673L;
#Transient
#ManagedProperty(value = "#{settings}")
private Settings settings;
#Id
private Date create_date;
private Integer person_ID;
public Date getCreate_date() {
return create_date;
}
public void setCreate_date(Date create_date) {
this.create_date = create_date;
}
public Integer getPerson_ID() {
return person_ID;
}
public void setPerson_ID(Integer person_ID) {
this.person_ID = person_ID;
try
{
Settings.PWKITEM = (Pwk)Tools.find(person_ID);
if (Settings.PWKITEM != null) settings.setUserfound(true); /// PROBLEMATIC
}
catch (Exception e)
{
Tools.setErrorMessage("NOT FOUND "+e.getMessage());
}
}
// ManagedProperty settings ---------------------------------------------
public Settings getSettings() {
return settings;
}
public void setSettings(Settings settings) {
this.settings = settings;
}
public void setUserfound (boolean userfound){
settings.setUserfound(userfound);
}
public boolean isUserfound() {
return settings.isUserfound();
}
}
Settings.java:
#SessionScoped
#ManagedBean(name="settings")
public class Settings implements Serializable
{
/**/
private static final long serialVersionUID = 8613411699115714416L;
public static Pwk PWKITEM = new Pwk();
private boolean userfound = false;
public boolean isUserfound() {
return userfound;
}
public void setUserfound(boolean userfound) {
this.userfound = userfound;
}
}
XHTML (ajax call setPerson_ID):
<h:inputText id="persId" value="#{bean.bdeitem.persId}">
<f:ajax event="blur" render="name" execute="#this" />
</h:inputText>
<h:inputText id="name" value="#{bean.pwkitem.name}"/>
Problem is in try/catch:
without the condition, object is found.
when I change the condition for example to if (Settings.PWKITEM != null) System.out.println("HELLO"), HELLO is writen to console.
if i try to add the userfound setter, it is catched ("NOT FOUND").
What I'm doing wrong?
Your question looks seriously confusing. You first show some bean code and then immediately say "I though that is an ajax problem,", before even mentioning any kind of problem. The rest of the question is not much different.
To directly answer the last part of your question though:
Ican't understand, why it find the item an writes the correct name to console, and immediatelly after that, it writes catch exception not found....????
You are accessing Settings statically. The instance you have declared at the class level seems to be useless. It's fully possible that if Tools.find throws an exception and thus no new value is assigned, that there is still an old value in the static Settings.PWKITEM field. There is nothing strange about that.
Do note that the log reads from top to bottom. So it's not that "***" is printed and then the exception is thrown, but the exception is first thrown and "Not Found" is printed, and only thereafter "***" is printed.
Additionally, your approach to all of this looks problematic. Declaring an Entity to also be a (JSF) backing bean is rarely a good idea. Using references to some kind of Service or DAO classes from within an entity is also not always a good idea, but doing this in a method that is supposedly a simple setter for an ID simply looks wrong.
Then using static references is even more wrong and to top if off, using underscores in method and non-static variable names goes against the common Java code convention.