How to add Method Expression to a custom JSF component - jsf-2

I'm trying to create a custom JSF component and add to it a method expression. This is the code of my custom component:
#FacesComponent(AjaxCommand2.COMPONENT_TYPE)
public class AjaxCommand2 extends UIComponentBase {
public static final String COMPONENT_TYPE = "local.test.component.AjaxCommand2";
public static final String COMPONENT_FAMILY = "local.test.component.AjaxCommand2";
private MethodExpression listener;
public MethodExpression getListener() {
return listener;
}
public void setListener(MethodExpression listener) {
this.listener = listener;
}
#Override
public String getRendererType() {
return null;
}
#Override
public String getFamily() {
return COMPONENT_FAMILY;
}
}
This is my tag lib file:
<?xml version="1.0" encoding="UTF-8"?>
<facelet-taglib id="test"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd" version="2.0">
<namespace>http://local.test/ui</namespace>
<tag>
<tag-name>ajaxCommand2</tag-name>
<component>
<component-type>local.test.component.AjaxCommand2</component-type>
</component>
<attribute>
<name>listener</name>
<required>false</required>
<type>javax.el.MethodExpression</type>
</attribute>
</tag>
</facelet-taglib>
And this is the relevant code in the JSF page:
<test:ajaxCommand2 listener="#{testSessionBean.testActionAjax}" />
My problem is that the setter for listener never is called in my custom component and always I'm getting null in listener property.
I cannot see whrere is the problem.
Any idea?, I would like set the listener property to point to a specific method of one backed bean.

Write a Handler for the Component like this:
public class MoveHandler extends ComponentHandler {
public MoveHandler(ComponentConfig config) {
super(config);
}
#Override
protected MetaRuleset createMetaRuleset(Class type) {
MetaRuleset metaRuleset = super.createMetaRuleset(type);
MetaRule metaRule = new MethodRule("listener", void.class, new Class[] {MoveEvent.class});
metaRuleset.addRule(metaRule);
return metaRuleset;
}
}

Related

Not getting screenshot in mobile ios allure reports

I tried to get screenshot in my allure reports with Appium on IOS real device and I'm not getting it, what I did is :
in my mainRunner :
#Listeners({ utilities.AllureListeners.class })
in my Allurelisteners :
public class AllureListeners implements ITestListener {
IOSBaseTest iosBaseTest = new IOSBaseTest();
public void onTestStart(ITestContext iTestContext) {
System.out.println("I am on start method "+ iTestContext.getName());
iTestContext.setAttribute("Driver", iosBaseTest.driver);
}
#Override
public void onTestSuccess(ITestResult result) {
System.out.println("I am on start method "+ getTestMethodName(result));
}
#Override
public void onTestFailure(ITestResult result) {
System.out.println("I am on testFailure method " + getTestMethodName(result)+" failed");
//Object testClass = result.getInstance();
//ITestContext context = result.getTestContext();
//WebDriver driver = (WebDriver) context.getAttribute("driver");
IOSDriver<MobileElement> driver = iosBaseTest.getdriver();
if (driver instanceof WebDriver) {
System.out.println("Screenshot captured for test case: "+getTestMethodName(result));
saveFailureScreenShot(driver);
}
saveTextLog(getTestMethodName(result) + "failed and screenshot taken!");
}
#Override
public void onTestSkipped(ITestResult result) {
System.out.println("I am on test skipped method "+getTestMethodName(result)+" skipped");
}
#Override
public void onTestFailedButWithinSuccessPercentage(ITestResult result) {
}
#Override
public void onTestFailedWithTimeout(ITestResult result) {
}
#Override
public void onStart(ITestContext context) {
}
#Override
public void onFinish(ITestContext context) {
}
private static String getTestMethodName(ITestResult iTestResult) {
return iTestResult.getMethod().getConstructorOrMethod().getName();
}
// Screenshot attachments for allure
#Attachment (value ="page screenshot", type = "image/png")
public byte[] saveFailureScreenShot(WebDriver driver) {
return ((TakesScreenshot)driver).getScreenshotAs(OutputType.BYTES);
}
// Text attachments for allure
#Attachment(value= "{0}", type = "text/plain")
public static String saveTextLog(String message) {
return message;
}
//HTML attachments for allure
#Attachment(value= "{0}", type = "text/html")
public static String attachHtml(String html) {
return html;
}
}
in my Base test I have method:
public IOSDriver<MobileElement> getdriver(){
return driver;
}
my xml is:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="Suite">
<listeners>
<listener class-name="utilities.AllureListeners" />
</listeners>
<test name="tester">
<groups>
<run>
<include name="add favorite contact" />
</run>
</groups>
<classes>
<class name="tests.IOSMainRunner">
</class>
</classes>
</test>
</suite>
and yet my report looking without a screenshot:
try this.
public void allureSaveDeviceScreenshot() {
Allure.addAttachment("screenshot", new ByteArrayInputStream(((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES)));
}

populate images with firebase recycler adapter through databinding

I am populating a firebase data with firebase recycler adapter through databinding and want to populate images with the data either from Picasso or Glide, but unable to do. So can any one help me what to write and where to write the code of either Picasso or Glide.
public class ShopByCategoryFragment extends Fragment {
FirebaseRecyclerAdapter adapter;
Firebase mFirebaseRef = new Firebase("https://abc.firebaseio.com/").child("subCategories");
public ShopByCategoryFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.recycler_view, container, false);
final RecyclerView recyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);
adapter = new FirebaseRecyclerAdapter<SubCategories, ViewHolder>(SubCategories.class, R.layout.fragment_shop_by_category,
ViewHolder.class, mFirebaseRef) {
#Override
protected void populateViewHolder(ViewHolder viewHolder, SubCategories subCategories, int i) {
FragmentShopByCategoryBinding binding = viewHolder.getBinding();
binding.setSubCategories(subCategories);
}
};
recyclerView.setAdapter(adapter);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 2));
return rootView;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public FragmentShopByCategoryBinding binding;
public ViewHolder(View itemView) {
super(itemView);
binding = DataBindingUtil.bind(itemView);
}
public FragmentShopByCategoryBinding getBinding() {
return binding;
}
}
#Override
public void onDestroy() {
super.onDestroy();
adapter.cleanup();
}
}
<layout xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="SubCategories"
type="com.abc.www.shopping.model.SubCategories"/>
</data>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_width="wrap_content"
android:layout_height="#dimen/tile_height"
android:id="#+id/sub_category_image"
android:scaleType="centerCrop"
android:src="#{SubCategories.image}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="#dimen/tile_height"
android:text="#{SubCategories.title}"
android:id="#+id/sub_category_title"
android:padding="16dp"
android:textColor="#color/colorSubCategoryTitle"
android:layout_gravity="center"
android:textAppearance="#android:style/TextAppearance.Material.Title"
tools:targetApi="lollipop" />
</FrameLayout>
</android.support.v7.widget.CardView>
public class SubCategories extends BaseObservable {
private String title;
private String image;
public SubCategories() {
// empty constructor
}
public SubCategories(String title, String image) {
this.title = title;
this.image = image;
}
public String getTitle() {
return title;
}
public String getImage() {
return image;
}
}
I have made something similar to what you need. I'll share my code and do a little explanation.
I have a class that returns the FirebaseRecyclerAdapter like this:
public RecyclerView.Adapter postAdapter(String userKey, final Context context, MyClickListener clickListener) {
Query userPostRef = postRef.child(userKey);
myClickListener = clickListener;
return new FirebaseRecyclerAdapter<PostModel, DataObjectHolder>(PostModel.class, R.layout.stream_layout, DataObjectHolder.class, userPostRef) {
#Override
public void populateViewHolder(final DataObjectHolder dataviewHolder, final PostModel postModel, int position) {
StorageReference mStorageRef = FirebaseStorage.getInstance().getReference();
mStorageRef.child("uploaded_captures/" + postModel.getImageFilename() + ".jpg").getDownloadUrl()
.addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
dataviewHolder.setImage(uri.toString(), context);
dataviewHolder.setComment(postModel.getPostComment());
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
Log.e("FirebaseRecyclerAdapter", exception.getMessage());
}
});
}
};
}
and a ViewHolder that loads the image into the ImageView used by the layout:
private static class DataObjectHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
View mView;
public DataObjectHolder(View itemView) {
super(itemView);
mView = itemView;
}
void setImage(final String imageURL, final Context context) {
final ImageView postImage = (ImageView) mView.findViewById(R.id.imageView);
if (BuildConfig.DEBUG) {
Picasso.with(context).setIndicatorsEnabled(true);
}
Picasso.with(context)
.load(imageURL)
.networkPolicy(NetworkPolicy.OFFLINE)
.placeholder(R.drawable.ic_menu_camera)
.fit().centerCrop().into(postImage, new Callback() {
#Override
public void onSuccess() {
}
#Override
public void onError() {
Picasso.with(context)
.load(imageURL)
.placeholder(R.drawable.ic_menu_camera)
.fit().centerCrop().into(postImage);
}
});
}
void setComment(String text) {
TextView comment = (TextView) mView.findViewById(R.id.comment);
comment.setText(text);
}
#Override
public void onClick(View v) {
myClickListener.onItemClick(getAdapterPosition(), v);
}
}
On Picasso I'm using the NerworkPolicy.OFFLINE to check if the image is on the disk cache before trying to get it from the network. It's not perfect and I'm still having some issues with the delay of the images once the ViewHolder it's been recycled but I think it's a start for you to go on.
In my ViewHolder I do this by:
Glide.with(context)
.load(chat.getImageUrl())
.into(imageView);
I haven't tried using data binding for this yet, but the code is simple enough.

Can't implement Phase Listener in jsf

I am trying to use phase Listener in one of my beans in jsf but it's not working.
Class:
package com.mycompany.creditcard1;
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.faces.context.FacesContext;
import javax.faces.context.Flash;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
#Named(value = "userDetailsLogin1")
#ViewScoped
public class UserDetailsLogin1 implements Serializable, PhaseListener {
private UserDetails userDetails;
Flash flash = FacesContext.getCurrentInstance().getExternalContext().getFlash();
#PostConstruct
public void init() {
System.out.println("inti");
userDetails = (UserDetails) flash.get("userDetails");
if (userDetails == null) {
userDetails = new UserDetails();
}
}
public UserDetailsLogin1() {
}
public UserDetails getUserDetails() {
return userDetails;
}
public String action() {
flash.put("userDetails", userDetails);
return "UserDetailsLogin2?faces-redirect=true";
}
#Override
public void afterPhase(PhaseEvent pe) {
System.out.println("after phase");
}
#Override
public void beforePhase(PhaseEvent pe) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
#Override
public PhaseId getPhaseId() {
return PhaseId.RESTORE_VIEW;
}
}
faces-config file:
<?xml version='1.0' encoding='UTF-8'?>
<faces-config version="2.2"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd">
<lifecycle>
<phase-listener>com.mycompany.creditcard1.MyPhaseListener</phase-listener>
</lifecycle>
Error:
Unable to create a new instance of 'com.mycompany.creditcard1.MyPhaseListener': javax.faces.FacesException: com.mycompany.creditcard1.MyPhaseListener
Don't understand why it is showing this?
Any help!!!
Well start by replacing <phase-listener>com.mycompany.creditcard1.MyPhaseListener</phase-listener> by <phase-listener>com.mycompany.creditcard1.UserDetailsLogin1</phase-listener>... you have the wrong class name!
Also, I don't know if it is a good practice to mixup Bean and PhaseListener into the same class...

can you have a taghandler class for a composite component (xhtml-based)

As soon as I define a composite component in a .taglib.xml to have a <handler-class>, the .xhtml file is ignored.
What I need is a xhtml/facelet based component with a component-type (UIComponent-derived class) and(!) also with a taghandler class. My aim is to catch all working on its child tags in order to be able to activate a custom cdi scope during this.
I found a way by looking at the richfaces impl.jar.
<?xml version="1.0" encoding="UTF-8"?>
<faces-config version="2.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd">
<factory>
<tag-handler-delegate-factory>de.sundn.regionscoped.jsf.BehaviorsTagHandlerDelegateFactoryImpl</tag-handler-delegate-factory>
</factory>
</faces-config>
Implement the factory
package de.sundn.regionscoped.jsf;
import javax.faces.FacesWrapper;
import javax.faces.view.facelets.BehaviorHandler;
import javax.faces.view.facelets.ComponentHandler;
import javax.faces.view.facelets.ConverterHandler;
import javax.faces.view.facelets.TagHandlerDelegate;
import javax.faces.view.facelets.TagHandlerDelegateFactory;
import javax.faces.view.facelets.ValidatorHandler;
/**
* #author Nick Belaevski
*/
public class BehaviorsTagHandlerDelegateFactoryImpl extends TagHandlerDelegateFactory implements
FacesWrapper<TagHandlerDelegateFactory> {
private TagHandlerDelegateFactory factory;
public BehaviorsTagHandlerDelegateFactoryImpl(TagHandlerDelegateFactory factory) {
this.factory = factory;
}
#Override
public TagHandlerDelegate createBehaviorHandlerDelegate(BehaviorHandler owner) {
return factory.createBehaviorHandlerDelegate(owner);
}
#Override
public TagHandlerDelegate createComponentHandlerDelegate(ComponentHandler owner) {
// TagHandlers structure is created when view is compiled
// so there's no need to check for BehaviorsStack
if (owner instanceof BehaviorsAddingComponentHandlerWrapper) {
// this is to avoid StackOverflowError because of ComponentHandler constructor call
return null;
}
ComponentHandler wrappedHandler = new BehaviorsAddingComponentHandlerWrapper(owner);
return factory.createComponentHandlerDelegate(wrappedHandler);
}
#Override
public TagHandlerDelegate createConverterHandlerDelegate(ConverterHandler owner) {
return factory.createConverterHandlerDelegate(owner);
}
#Override
public TagHandlerDelegate createValidatorHandlerDelegate(ValidatorHandler owner) {
return factory.createValidatorHandlerDelegate(owner);
}
#Override
public TagHandlerDelegateFactory getWrapped() {
return factory;
}
}

How to get parent of a custom component?

I have a custom container component, that I want to use like this:
<p:a>A
<p:a>B</p:a>
</p:a>
That should generate this markup:
<div>A
<div>B</div>
</div>
Code for the component is below.
public class TagA extends TagHandler {
Logger logger = Logger.getLogger(getClass().getName());
public TagA(TagConfig config) {
super(config);
}
public void apply(FaceletContext ctx, UIComponent parent)
throws IOException {
UIComponentBase c = new UIComponentBase() {
public void encodeBegin(FacesContext ctx) throws IOException {
//getParent() always returns UIViewRot
logger.info("Parent is: " + getParent().getClass().getName());
ResponseWriter w = ctx.getResponseWriter();
w.write("<div>");
super.encodeBegin(ctx);
}
public void encodeEnd(FacesContext ctx) throws IOException {
ResponseWriter w = ctx.getResponseWriter();
w.write("</div>");
super.encodeEnd(ctx);
}
// abstract method in base, must override
public String getFamily() {
return "com.mobiarch.nf";
}
};
parent.getChildren().add(c);
nextHandler.apply(ctx, parent);
}
}
Unfortunately, this is rendering the following markup:
<div></div>A
<div></div>B
For others in a similar situation, just develop the component and not the tag.
#FacesComponent("my.ComponentA")
public class ComponentA extends UIComponentBase {
Logger logger = Logger.getLogger(getClass().getName());
public String getFamily() {
return "my.custom.component";
}
public void encodeBegin(FacesContext ctx) throws IOException {
super.encodeBegin(ctx);
logger.info("Component parent is: " + getParent().getClass().getName());
ResponseWriter w = ctx.getResponseWriter();
w.write("<div>");
}
public void encodeEnd(FacesContext ctx) throws IOException {
super.encodeEnd(ctx);
ResponseWriter w = ctx.getResponseWriter();
w.write("</div>");
}
}
Register it in your ??.taglib.xml
<tag>
<tag-name>a</tag-name>
<component>
<component-type>my.ComponentA</component-type>
</component>
</tag>

Resources