IceFaces Copies PrimeFaces Line by Line

After release of IceFaces 3, we have been getting reports from PrimeFaces Community that IceFaces Ace Components look similar to PrimeFaces. After looking at Ice Ace Components, frankly, we are shocked and disappointed! IceSoft copied PrimeFaces code LINE BY LINE to come up with it’s new set of components named Ace. We are aware that we can’t take any action legally as code is open however we just want to let you know about this. Here is an example of PrimeFaces Panel and Ice Panel as a case study;

PrimeFaces PanelRenderer

package org.primefaces.component.panel;

import java.io.IOException;
import java.util.Map;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;

import org.primefaces.component.menu.Menu;
import org.primefaces.renderkit.CoreRenderer;

public class PanelRenderer extends CoreRenderer {

    @Override
    public void decode(FacesContext context, UIComponent component) {
        Panel panel = (Panel) component;
        String clientId = panel.getClientId(context);
        Map params = context.getExternalContext().getRequestParameterMap();

        //Restore toggle state
        String collapsedParam = params.get(clientId + "_collapsed");
        if(collapsedParam != null) {
            panel.setCollapsed(Boolean.valueOf(collapsedParam));
        }

        //Restore visibility state
        String visibleParam = params.get(clientId + "_visible");
        if(visibleParam != null) {
            panel.setVisible(Boolean.valueOf(visibleParam));
        }

        decodeBehaviors(context, component);
    }

    @Override
    public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException {
        Panel panel = (Panel) component;

        encodeMarkup(facesContext, panel);
        encodeScript(facesContext, panel);
    }

    protected void encodeScript(FacesContext context, Panel panel) throws IOException {
        ResponseWriter writer = context.getResponseWriter();
        String clientId = panel.getClientId(context);

        startScript(writer, clientId);

        writer.write("PrimeFaces.cw('Panel','" + panel.resolveWidgetVar() + "',{");
        writer.write("id:'" + clientId + "'");

        //Toggle configuration
        if(panel.isToggleable()) {
            writer.write(",toggleable:true");
            writer.write(",toggleSpeed:" + panel.getToggleSpeed());
            writer.write(",collapsed:" + panel.isCollapsed());
        }

        //Toggle configuration
        if(panel.isClosable()) {
            writer.write(",closable:true");
            writer.write(",closeSpeed:" + panel.getCloseSpeed());
        }

        //Options menu configuration
        if(panel.getOptionsMenu() != null) {
            writer.write(",hasMenu:true");
        }

        encodeClientBehaviors(context, panel);

        writer.write("});");

        endScript(writer);
    }

    protected void encodeMarkup(FacesContext context, Panel panel) throws IOException {
        ResponseWriter writer = context.getResponseWriter();
        String clientId = panel.getClientId(context);
        Menu optionsMenu = panel.getOptionsMenu();

        writer.startElement("div", null);
        writer.writeAttribute("id", clientId, null);
        String styleClass = panel.getStyleClass() != null ? Panel.PANEL_CLASS + " " + panel.getStyleClass() : Panel.PANEL_CLASS;
        styleClass = panel.isVisible() ? styleClass : styleClass + " ui-helper-hidden";
        writer.writeAttribute("class", styleClass, "styleClass");
        if(panel.getStyle() != null) {
            writer.writeAttribute("style", panel.getStyle(), "style");
        }

        encodeHeader(context, panel);
        encodeContent(context, panel);
        encodeFooter(context, panel);

        if(panel.isToggleable()) {
            encodeStateHolder(context, panel, clientId + "_collapsed", String.valueOf(panel.isCollapsed()));
        }

        if(panel.isClosable()) {
            encodeStateHolder(context, panel, clientId + "_visible", String.valueOf(panel.isVisible()));
        }

        if (optionsMenu != null) {
            optionsMenu.setPosition("dynamic");
            optionsMenu.setTrigger(clientId + "_menu");
            optionsMenu.setMy("left top");
            optionsMenu.setAt("left bottom");

            optionsMenu.encodeAll(context);
        }

        writer.endElement("div");
    }

    protected void encodeHeader(FacesContext context, Panel panel) throws IOException {
        ResponseWriter writer = context.getResponseWriter();
        String widgetVar = panel.resolveWidgetVar();
        UIComponent header = panel.getFacet("header");
        String headerText = panel.getHeader();
        String clientId = panel.getClientId(context);

        if(headerText == null && header == null) {
            return;
        }

        writer.startElement("div", null);
        writer.writeAttribute("id", panel.getClientId(context) + "_header", null);
        writer.writeAttribute("class", Panel.PANEL_TITLEBAR_CLASS, null);

        //Title
        writer.startElement("span", null);
        writer.writeAttribute("class", Panel.PANEL_TITLE_CLASS, null);

        if(header != null) {
            renderChild(context, header);
        } else if(headerText != null) {
            writer.write(headerText);
        }

        writer.endElement("span");

        //Options
        if(panel.isClosable()) {
            encodeIcon(context, panel, "ui-icon-closethick", clientId + "_closer", panel.getCloseTitle());
        }

        if(panel.isToggleable()) {
            String icon = panel.isCollapsed() ? "ui-icon-plusthick" : "ui-icon-minusthick";
            encodeIcon(context, panel, icon, clientId + "_toggler", panel.getToggleTitle());
        }

        if(panel.getOptionsMenu() != null) {
            encodeIcon(context, panel, "ui-icon-gear", clientId + "_menu", panel.getMenuTitle());
        }

        writer.endElement("div");
    }

    protected void encodeContent(FacesContext facesContext, Panel panel) throws IOException {
        ResponseWriter writer = facesContext.getResponseWriter();

        writer.startElement("div", null);
        writer.writeAttribute("id", panel.getClientId() + "_content", null);
        writer.writeAttribute("class", Panel.PANEL_CONTENT_CLASS, null);
        if (panel.isCollapsed()) {
            writer.writeAttribute("style", "display:none", null);
        }

        renderChildren(facesContext, panel);

        writer.endElement("div");
    }

    protected void encodeFooter(FacesContext facesContext, Panel panel) throws IOException {
        ResponseWriter writer = facesContext.getResponseWriter();
        UIComponent footer = panel.getFacet("footer");
        String footerText = panel.getFooter();

        if (footer != null || footerText != null) {
            writer.startElement("div", null);
            writer.writeAttribute("id", panel.getClientId(facesContext) + "_footer", null);
            writer.writeAttribute("class", Panel.PANEL_FOOTER_CLASS, null);

            if (footer != null) {
                renderChild(facesContext, footer);
            } else if (footerText != null) {
                writer.write(footerText);
            }

            writer.endElement("div");
        }
    }

    protected void encodeIcon(FacesContext context, Panel panel, String iconClass, String id, String title) throws IOException {
        ResponseWriter writer = context.getResponseWriter();

        writer.startElement("a", null);
        writer.writeAttribute("href", "javascript:void(0)", null);
        writer.writeAttribute("class", Panel.PANEL_TITLE_ICON_CLASS, null);
        if(title != null) {
            writer.writeAttribute("title", title, null);
        }

        writer.startElement("span", null);

        if(id != null) {
            writer.writeAttribute("id", id, null);
        }

        writer.writeAttribute("class", "ui-icon " + iconClass, null);

        writer.endElement("span");

        writer.endElement("a");
    }

    protected void encodeStateHolder(FacesContext context, Panel panel, String name, String value) throws IOException {
        ResponseWriter writer = context.getResponseWriter();

        writer.startElement("input", null);
        writer.writeAttribute("type", "hidden", null);
        writer.writeAttribute("id", name, null);
        writer.writeAttribute("name", name, null);
        writer.writeAttribute("value", value, null);
        writer.endElement("input");
    }

    @Override
    public void encodeChildren(FacesContext context, UIComponent component) throws IOException {
        //Do nothing
    }

    @Override
    public boolean getRendersChildren() {
        return true;
    }
}

IceFaces PanelRenderer

package org.icefaces.ace.component.panel;

import java.io.IOException;
import java.util.Map;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;

import org.icefaces.ace.component.menu.Menu;
import org.icefaces.ace.renderkit.CoreRenderer;

import org.icefaces.ace.util.Utils;
import org.icefaces.ace.util.JSONBuilder;
import org.icefaces.render.MandatoryResourceComponent;

@MandatoryResourceComponent(tagName="panel", value="org.icefaces.ace.component.panel.Panel")
public class PanelRenderer extends CoreRenderer {

    @Override
    public void decode(FacesContext context, UIComponent component) {
        Panel panel = (Panel) component;
        String clientId = panel.getClientId(context);
        Map params = context.getExternalContext().getRequestParameterMap();

        //Restore toggle state
        String collapsedParam = params.get(clientId + "_collapsed");
        if(collapsedParam != null) {
            panel.setCollapsed(Boolean.valueOf(collapsedParam));
        }

        //Restore visibility state
        String visibleParam = params.get(clientId + "_visible");
        if(visibleParam != null) {
            panel.setVisible(Boolean.valueOf(visibleParam));
        }

        decodeBehaviors(context, component);
    }

    @Override
    public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException {
        Panel panel = (Panel) component;

        encodeMarkup(facesContext, panel);
        encodeScript(facesContext, panel);
    }

    protected void encodeScript(FacesContext context, Panel panel) throws IOException {
        ResponseWriter writer = context.getResponseWriter();
        String clientId = panel.getClientId(context);

        writer.startElement("script", null);
        writer.writeAttribute("type", "text/javascript", null);

        writer.write(this.resolveWidgetVar(panel) + " = new ");
		JSONBuilder jb = JSONBuilder.create();
		jb.beginFunction("ice.ace.Panel")
			.item(clientId)
			.beginMap()
			.entry("visible", panel.isVisible());

        //Toggle configuration
        if(panel.isToggleable()) {
            jb.entry("toggleable", true);
            jb.entry("toggleSpeed", panel.getToggleSpeed());
            jb.entry("collapsed", panel.isCollapsed());
        }

        //Toggle configuration
        if(panel.isClosable()) {
            jb.entry("closable", true);
            jb.entry("closeSpeed", panel.getCloseSpeed());
        }

        //Options menu configuration
        if(panel.getOptionsMenu() != null) {
            jb.entry("hasMenu", true);
        }

        encodeClientBehaviors(context, panel, jb);

        jb.endMap().endFunction();
		writer.write(jb.toString());

        writer.endElement("script");
    }

    protected void encodeMarkup(FacesContext context, Panel panel) throws IOException {
        ResponseWriter writer = context.getResponseWriter();
        String clientId = panel.getClientId(context);
        Menu optionsMenu = panel.getOptionsMenu();

        writer.startElement("div", null);
        writer.writeAttribute("id", clientId, null);

        String styleClass = panel.getStyleClass() ;
		Utils.writeConcatenatedStyleClasses(writer, Panel.PANEL_CLASS, styleClass);
		String style = panel.getStyle();
        if(style != null) {
            writer.writeAttribute("style", style, "style");
        }

        encodeHeader(context, panel);
        encodeContent(context, panel);
        encodeFooter(context, panel);

        if(panel.isToggleable()) {
            encodeStateHolder(context, panel, clientId + "_collapsed", String.valueOf(panel.isCollapsed()));
        }

        if(panel.isClosable()) {
            encodeStateHolder(context, panel, clientId + "_visible", String.valueOf(panel.isVisible()));
        }

        if (optionsMenu != null) {
            optionsMenu.setPosition("dynamic");
            optionsMenu.setTrigger(clientId + "_menu");
            optionsMenu.setMy("left top");
            optionsMenu.setAt("left bottom");

            optionsMenu.encodeAll(context);
        }

        writer.endElement("div");
    }

    protected void encodeHeader(FacesContext context, Panel panel) throws IOException {
        ResponseWriter writer = context.getResponseWriter();
        String widgetVar = this.resolveWidgetVar(panel);
        UIComponent header = panel.getFacet("header");
        String headerText = panel.getHeader();
        String clientId = panel.getClientId(context);

        if(headerText == null && header == null) {
            return;
        }

        writer.startElement("div", null);
        writer.writeAttribute("id", clientId + "_header", null);
        writer.writeAttribute("class", Panel.PANEL_TITLEBAR_CLASS, null);

        //Title
        writer.startElement("span", null);
        writer.writeAttribute("class", Panel.PANEL_TITLE_CLASS, null);

        if(header != null) {
            renderChild(context, header);
        } else if(headerText != null) {
            writer.write(headerText);
        }

        writer.endElement("span");

        //Options
        if(panel.isClosable()) {
            encodeIcon(context, panel, "ui-icon-closethick", clientId + "_closer");
        }

        if(panel.isToggleable()) {
            String icon = panel.isCollapsed() ? "ui-icon-plusthick" : "ui-icon-minusthick";
            encodeIcon(context, panel, icon, clientId + "_toggler");
        }

        if(panel.getOptionsMenu() != null) {
            encodeIcon(context, panel, "ui-icon-gear", clientId + "_menu");
        }

        writer.endElement("div");
    }

    protected void encodeContent(FacesContext facesContext, Panel panel) throws IOException {
        ResponseWriter writer = facesContext.getResponseWriter();

        writer.startElement("div", null);
        writer.writeAttribute("id", panel.getClientId() + "_content", null);
        writer.writeAttribute("class", Panel.PANEL_CONTENT_CLASS, null);
        if (panel.isCollapsed()) {
            writer.writeAttribute("style", "display:none", null);
        }

        renderChildren(facesContext, panel);

        writer.endElement("div");
    }

    protected void encodeFooter(FacesContext facesContext, Panel panel) throws IOException {
        ResponseWriter writer = facesContext.getResponseWriter();
        UIComponent footer = panel.getFacet("footer");
        String footerText = panel.getFooter();

        if (footer != null || footerText != null) {
            writer.startElement("div", null);
            writer.writeAttribute("id", panel.getClientId(facesContext) + "_footer", null);
            writer.writeAttribute("class", Panel.PANEL_FOOTER_CLASS, null);

            if (footer != null) {
                renderChild(facesContext, footer);
            } else if (footerText != null) {
                writer.write(footerText);
            }

            writer.endElement("div");
        }
    }

    protected void encodeIcon(FacesContext context, Panel panel, String iconClass, String id) throws IOException {
        ResponseWriter writer = context.getResponseWriter();

        writer.startElement("a", null);
        writer.writeAttribute("class", Panel.PANEL_TITLE_ICON_CLASS, null);

        writer.startElement("span", null);

        if(id != null) {
            writer.writeAttribute("id", id, null);
        }

        writer.writeAttribute("class", "ui-icon " + iconClass, null);

        writer.endElement("span");

        writer.endElement("a");
    }

    protected void encodeStateHolder(FacesContext context, Panel panel, String name, String value) throws IOException {
        ResponseWriter writer = context.getResponseWriter();

        writer.startElement("input", null);
        writer.writeAttribute("type", "hidden", null);
        writer.writeAttribute("id", name, null);
        writer.writeAttribute("name", name, null);
        writer.writeAttribute("value", value, null);
        writer.endElement("input");
    }

    @Override
    public void encodeChildren(FacesContext context, UIComponent component) throws IOException {
        //Do nothing
    }

    @Override
    public boolean getRendersChildren() {
        return true;
    }
}

PrimeFaces Panel.js

/**
 * PrimeFaces Panel Widget
 */
PrimeFaces.widget.Panel = function(cfg) {
    this.cfg = cfg;
    this.id = this.cfg.id;
    this.jqId = PrimeFaces.escapeClientId(this.id);

    if(this.cfg.toggleable) {
        this.toggler = $(this.jqId + '_toggler');
        this.toggleStateHolder = $(this.jqId + '_collapsed');
        this.content = $(this.jqId + '_content');

        this.setupToggleTrigger();
    }

    if(this.cfg.closable) {
        this.visibleStateHolder = $(this.jqId + "_visible");

        this.setupCloseTrigger();
    }

    if(this.cfg.hasMenu) {
        this.visibleStateHolder = $(this.jqId + "_visible");

        this.setupMenuTrigger();
    }

    this.postConstruct();
}

PrimeFaces.extend(PrimeFaces.widget.Panel, PrimeFaces.widget.BaseWidget);

PrimeFaces.widget.Panel.prototype.toggle = function() {
    if(this.cfg.collapsed) {
        this.toggler.removeClass('ui-icon-plusthick').addClass('ui-icon-minusthick');
        this.cfg.collapsed = false;
        this.toggleStateHolder.val(false);
    }
    else {
        this.toggler.removeClass('ui-icon-minusthick').addClass('ui-icon-plusthick');
        this.cfg.collapsed = true;
        this.toggleStateHolder.val(true);
    }

    var _self = this;

    this.content.slideToggle(this.cfg.toggleSpeed,
        function(e) {
            if(_self.cfg.behaviors) {
                var toggleBehavior = _self.cfg.behaviors['toggle'];
                if(toggleBehavior) {
                    toggleBehavior.call(_self, e);
                }
            }
        });
}

PrimeFaces.widget.Panel.prototype.close = function() {
    this.visibleStateHolder.val(false);

    var _self = this;

    $(this.jqId).fadeOut(this.cfg.closeSpeed,
        function(e) {
            if(_self.cfg.behaviors) {
                var closeBehavior = _self.cfg.behaviors['close'];
                if(closeBehavior) {
                    closeBehavior.call(_self, e);
                }
            }
        }
    );
}

PrimeFaces.widget.Panel.prototype.show = function() {
    $(this.jqId).fadeIn(this.cfg.closeSpeed);

    this.visibleStateHolder.val(true);
}

PrimeFaces.widget.Panel.prototype.setupToggleTrigger = function() {
    var _self = this,
    trigger = this.toggler.parent();

    this.setupTriggerVisuals(trigger);

    trigger.click(function() {_self.toggle();});
}

PrimeFaces.widget.Panel.prototype.setupCloseTrigger = function() {
    var _self = this,
    trigger = $(this.jqId + '_closer').parent();

    this.setupTriggerVisuals(trigger);

    trigger.click(function() {_self.close();});
}

PrimeFaces.widget.Panel.prototype.setupMenuTrigger = function() {
    var trigger = $(this.jqId + '_menu').parent();

    this.setupTriggerVisuals(trigger);
}

PrimeFaces.widget.Panel.prototype.setupTriggerVisuals = function(trigger) {
    trigger.mouseover(function() {$(this).addClass('ui-state-hover');})
            .mouseout(function() {$(this).removeClass('ui-state-hover');});
}

IceFaces Panel.js

/**
 *  Panel Widget
 */
ice.ace.Panel = function(id, cfg) {
    this.id = id;
    this.cfg = cfg;
    this.jqId = ice.ace.escapeClientId(id);

    if(this.cfg.toggleable) {
        this.toggler = ice.ace.jq(this.jqId + '_toggler');
        this.toggleStateHolder = ice.ace.jq(this.jqId + '_collapsed');
        this.content = ice.ace.jq(this.jqId + '_content');

        this.setupToggleTrigger();
    }

    if(this.cfg.closable) {
        this.visibleStateHolder = ice.ace.jq(this.jqId + "_visible");

        this.setupCloseTrigger();
    }

    if(this.cfg.hasMenu) {
        this.visibleStateHolder = ice.ace.jq(this.jqId + "_visible");

        this.setupMenuTrigger();
    }

    if(!this.cfg.visible) {
        ice.ace.jq(this.jqId).css('display','none');
    }
}

ice.ace.Panel.prototype.toggle = function() {
    if(this.cfg.collapsed) {
        this.toggler.removeClass('ui-icon-plusthick').addClass('ui-icon-minusthick');
        this.cfg.collapsed = false;
        this.toggleStateHolder.val(false);
    }
    else {
        this.toggler.removeClass('ui-icon-minusthick').addClass('ui-icon-plusthick');
        this.cfg.collapsed = true;
        this.toggleStateHolder.val(true);
    }

    var _self = this;

    this.content.slideToggle(this.cfg.toggleSpeed,
        function(e) {
            if(_self.cfg.behaviors) {
                var toggleBehavior = _self.cfg.behaviors['toggle'];
                if(toggleBehavior) {
                    toggleBehavior.call(this, e);
                }
            }
        });
}

ice.ace.Panel.prototype.close = function() {
    this.visibleStateHolder.val(false);

    var _self = this;

    ice.ace.jq(this.jqId).fadeOut(this.cfg.closeSpeed,
        function(e) {
            if(_self.cfg.behaviors) {
                var closeBehavior = _self.cfg.behaviors['close'];
                if(closeBehavior) {
                    closeBehavior.call(this, e);
                }
            }
        }
    );
}

ice.ace.Panel.prototype.show = function() {
    ice.ace.jq(this.jqId).fadeIn(this.cfg.closeSpeed);

    this.visibleStateHolder.val(true);
}

ice.ace.Panel.prototype.setupToggleTrigger = function() {
    var _self = this,
    trigger = this.toggler.parent();

    this.setupTriggerVisuals(trigger);

    trigger.click(function() {_self.toggle();});
}

ice.ace.Panel.prototype.setupCloseTrigger = function() {
    var _self = this,
    trigger = ice.ace.jq(this.jqId + '_closer').parent();

    this.setupTriggerVisuals(trigger);

    trigger.click(function() {_self.close();});
}

ice.ace.Panel.prototype.setupMenuTrigger = function() {
    var trigger = ice.ace.jq(this.jqId + '_menu').parent();

    this.setupTriggerVisuals(trigger);
}

ice.ace.Panel.prototype.setupTriggerVisuals = function(trigger) {
    trigger.mouseover(function() {ice.ace.jq(this).addClass('ui-state-hover');})
            .mouseout(function() {ice.ace.jq(this).removeClass('ui-state-hover');});
}

We have looked in detail of all IceFaces Ace Components and more than 90% of IceFaces components are like Panel. They are copied line by line, only difference is the change of package names from prime to ice. This duplication applies to java renderers, components codes, javascripts and css files as well.

License of IceFaces components start with this line;

“Original Code developed and contributed by Prime Technology. Subsequent Code Modifications Copyright 2011-2012 ICEsoft Technologies Canada Corp. (c)”

First of all we are not aware of any “contribution”, we haven’t done any contribution to IceFaces or signed any contribution agreement just like a CLA (Contributor License Agreement). Their code includes reference to our work with the line above, however nowhere on their release announcements here or here this was mentioned at all, it’s like they have written the code themselves. This “tiny” detail is hidden from public and marketing point of view. This also explains why IceFaces license is now Apache, because PrimeFaces is Apache.

IceFaces has lost significant of it’s user base to PrimeFaces since 2009 and they are trying to get their popularity back. Last year, IceSoft has approached us with the idea of sponsoring PrimeFaces by paying 60K $ per year. Our clear answer was a big NO, it seems after getting rejected, they have chosen a very very wrong way when trying to build their new ACE Components that is aimed to replace their legacy components, which is copying our code line by line and offer commercial services like support, consulting and training over our copy-paste code. Competition should be about providing alternative solutions not copy-paste your competitors just because the license permits and it is legal.

We’ve also realized that IceSoft has copied the code from PrimeFaces 2 which was released a year ago, PrimeFaces 3 is much better than PrimeFaces 2, this seems to be second mistake of IceFaces. They have copied the wrong branch!.

We don’t think there is a stealing here as the code is open and free to anyone. Incorporating OSS code in another OSS code is totally fine and result of OSS nature. However we think it is wrong and not cool when the two OSS products are competing and on the same line. There are various OSS projects that use PrimeFaces out there, all of them link to PrimeFaces and use the library, none of them actually copies the code and renames the packages like Ice does. We’ll be happy if IceSoft updates their Ace component pages or release announcements to add the fact that, IceFaces Ace components are forked from PrimeFaces Codebase instead of advertising it as a home grown product. We don’t see a public reference or a credits in NOTICE file in icefaces jar at all.

As of PrimeFaces 3, we use 3rd party libraries as minimal as possible, for example PrimeFaces 2 which IceFaces copies, use jQuery UI and YUI a lot. Components like accordion, tabview, menu, menubar, autocomplete, paginator, buttons and many more were based on 3rd party widgets. With PrimeFaces 3 we have written the client side widgets of these and more by ourselves with JSF in mind which gave us the power to add advanced new features that you can’t find in these widgets. PrimeFaces 1 or 2 can be seen as a wrapper of 3rd party libs but PrimeFaces 3 is not, we are even considering to externalize our own javascript library for non-jsf use. We spent our days, nights and weekends to come up with our own ideas and the implementation of our own ideas. This is the reason of our success, the passion! PrimeFaces has became the leading component suite as can be seen from Google Trends as well. In addition PrimeFaces is the RIA library with the most followers on twitter. At time of writing stats are PrimeFaces 2067, RichFaces 1687, IceFaces 951, Vaadin 1554, ZK 706.

In the end, we are not annoyed at all, just disappointed to see a competitor of PrimeFaces copying our code. It is really not that hard to create rich JSF components, it would be better if IceFaces implemented their own solutions and provided a new alternative to the JSF ecosystem. We don’t think anyone needs IceSoft to enhance PrimeFaces, we as PrimeFaces team have already done it and it is called PrimeFaces 3.

Please share this article on social media so we can let more people know about this!

!!!You may copy our code, but you’ll never take our PASSION!!!

Optimus Prime
On Behalf of All AutoBots in PrimeFaces Community

Updates

  • They have added this page after getting so much criticism from the community.om the community. This reveals PrimeFaces is a core technology of IceFaces. IceFaces is powered by PrimeFaces. It is great to hear that we are now powering our competitors. It is not stated but Slider, DateTimeEntry and Core Engine (core.js) is also based on jQuery/PrimeFaces.
  • Our posts and posts of many PrimeFaces users in IceFaces forums has been deleted by IceSoft. Free Speech!
  • We have done a new and final announcement regarding this to state our final words and leave this behind. Thanks everyone for their feedback!

 

This entry was posted in Uncategorized. Bookmark the permalink.

117 thoughts on “IceFaces Copies PrimeFaces Line by Line

  1. “!!!You may copy our code, but you’ll never take our PASSION!!!”

    Hey Optimus Prime!, lets see the positive side of this, It’s gonna be even easier for IceFaces users to move to PrimeFaces!! =)

    • I have to use IceFaces in some Projects because our clients want icefaces. From now on I will refuse to use icefaces in any project. Primefaces rulez!

  2. PrimeFaces has given lots to us, maybe it’s time to give some back to you. You should ask everybody to share this info in a massive way, I mean, by facebook, twitter, personally… anyway. By my side, our company is working with two more companies, they used icefaces until I introduced them primefaces, now their new projects are being developed with PF because they really liked it. I think it’s a good way to show them who is the best, and to let them know that copying it’s a wrong way to compete. Greetings

  3. It is unfortunate that we have different perspectives on the application of open source principles. I can assure you that we *have* added significant value to the PrimeFaces 2 component code that we chose to integrate into the ACE Components. Of course, all of our changes are available under that Apache 2 license and are freely available, so folks can decide for themselves.

    Please check out the link below if you’re interested in more information on our perspective on this:
    http://www.icefaces.org/JForum/posts/list/20499.page

    Regards,
    Ken

    • as a java developer ,you can pack js library ,but what you have done is to change the package name as you owner code .No developer will not by angry ! what you can do is to use primefaces as a library to let it work more fine and or pack it again to let it meet you owner demand . But you mustn’t only change the package name to announce it’s yours.what a shame ,icefaces !

  4. Wow, interesting blog. I’m sorry to hear about what IceFaces is doing. I’m glad to see you still have the passion. I’ve heard of ‘this’ IceFaces, but clearly not interested to ‘google’ it, and surely not interested in ‘using’ it. PrimeFaces is my choice, and as we see in this blog, PrimeFaces is even IceFaces’ ‘choice’, too!

  5. i can only see positive things.by copying PrimeFaces code they recognize it’s superiority.however people in general want the original not the copy …anyway it was not fair…but it might bring a lot of publicity to. primefaces

  6. @Jorge You got that right, mate! ;)
    @Optimus Prime: Look at the bright side: copying is the first sign of admiration… Anyway, PrimeFaces has proven its valor and maturity since ICEFaces has put up the effort to make some “Subsequent Code Modifications”.

  7. Wow, that is indeed brazenly. I still think it is ok, but they should at least give PrimeFaces proper credit (e.g. in release infos)

  8. WTF?!
    I use PrimeFaces since years now and I just can say: go on with the good work!
    There is a reason why PrimeFaces is the leading component library.
    IceFaces won’t get an extensive user base with this kind of philosophy.

  9. Hi,

    You say Open source project under the same License can ‘copy’ code from one another. But that’s not exactly right, the copyright MUST be preserved. So the Prime faces copyright MUST be visible on Icefaces files. Otherwise they assume you contributed under their copyright, which allows them to change the License in the futur (even to something private if they want). This is a big issue here.

    OpenSolaris project is a good example, everything was contributed under gpl with Orable copyright, and Oracle decided to make it private and they did, with all free contributors code ! (the free project continues as illuminos) Still Free code have become ‘private’.

    So, do you want something similar to happen to prime-faces ?

    • I love primeface . And I don’t see primefaces become private again. Maybe the real result of icefaces that coping code line by line is to force primefaces become private again .

  10. So… the Decepticons are back……………….
    Still, they’re no match for the autobots!!!!!!!

  11. adamların üniversitede milletten lab alıp değişken isimlerini değiştirerek yollayan öğrenci modunda open source library geliştirmesi çok iyi :D

  12. Disappointing indeed.

    Don’t be too downhearted. Anyone who wants to use the best RIA package available goes straight to the Primefaces web site anyway.

  13. Nice to see that IceFaces have thoroughly vindicated our decision to use PrimeFaces!
    And obviously they are ALWAYS going to trail yourselves in releases if they can’t deliver any innovation.
    As for slavishly copying lock, stock and barrel, it’s just shameful, never mind the near theft by non-attribution!

  14. What they did looks like legal, unfortunately, but if there is anything you can do, you should do.

    I also think this is the death of IceFaces. Why would anyone use a bad copy instead of the real thing?

  15. Its a compliment ! Now you can say PrimeFaces is so good that even IceFaces uses PrimeFaces !

  16. Today is the best library Primefaces jsf, other do not compare. And as the evolution of the press is quick, if it continues, even copying will always be behind.

  17. To be fair, the FAQ for ICEfaces ACE says this:

    “The ACE library includes custom components developed by ICEsoft as well as “best-of-breed” components sourced from popular third party open source libraries such as jQuery, YUI and PrimeFaces.”

    http://www.icesoft.org/projects/ICEfaces/ace-faq.jsf

    @MSC: How is it unfortunate that what ICEfaces did is legal? It’s only legal because PrimeFaces is an Open Source library, which is a very good and fortunate thing. The unfortunate thing is not the legality of it, but the fact that ICE didn’t do something new.

    • No, it’s not unfortunate that PrimeFaces being open source, it is great. It is unfortunate because PF team can do (almost) nothing about a competitor stealing the efforts they put. Because the license allows it, legal efforts would not lead to a meaningful result.

      • The best response to IceFaces would be that the development community to drop using IceFaces and switch to PrimeFaces. The icefaces code is a copy of a recent version of primefaces anyway. This action clearly indicates that IceFaces has thrown the towel and started imitating competitor products, instead of innovation

    • Those that are saying that Icefaces state that they use components from Primefaces is one thing. Copying code from one code base into another and changing package names, thus presenting code as ‘your own’ is quite another. At best it’s weasly at worst it misrepresents the skill of the Iceface developers.

      If you want real expertise you won’t touch Icefaces with a 10 foot pole.

  18. Never mind any possible legal issues, what about the ethical ones?
    If IceSoft really wanted to contribute to PF Open Source as they claimed they could and in my opinion, should have made their changes to the original PF code and offered to check their “improvements” back into the PF 2 code, perhaps as a branch. Instead they made the code look like their own, paid lip service to the legal requirements and had the cheek to then say that this is a major step forward in the product they are selling.
    Let us not forget that IceFaces does not come close to the component count in the open source project that PrimeFaces does.

    Thankfully IceSoft chose to use an old branch – IceFaces 3 is the best they can offer as Open Source? Are they trying to kill their product off?

  19. Optimus I understand You. Let’s vote for ACTA :) . Only what we can do is saying to the world that ifcefaces is based on PrimeFaces. So, what sense is tu use IceFaces when you have for free PrimeFaces?

  20. I think that the only thing you should really be disappointed about is the lack of credit from the ICEfaces team. Being copied shamelessly is indeed the risk of having such an open license. It all depends on the Prime Technology business model which appears to be truly community-based in contrast to the ICEFaces one. Perhaps it is time to reconsider what you really want to do with this awesome set of components that can leverage so many JSF2 development projects all over the world.
    Using a community-edition / standard-edition model (shareware) -model like ICEFaces or Orbeon Forms does means that downloaders do not get the full package and are less enthusiastic. Perhaps having a stricter license for contributors(component developers) and enabling users(component users) to download the binaries only is a solution(Java’s WORA advantage). Since this makes everybody happy with a full set of components and yet leaves Prime Technology in charge.

    As with all changes in supply-and-demand models, the benefits of open source development need to be found by crossing it’s beneficial boundaries. This is -I think- what just happened.

  21. I think no one will trust ICE faces!
    Why?
    because in software INNOVATION is the most important factor to make a company successful !!!
    But unfortunately ICE faces is just copying others innovations!!!!
    I saw their showcase! it is just a fork from primefaces (What a shame! :D )
    They say that: this is open source!! but I think this is not fair!
    I will never trust theme and I will prevent others to use it !!
    Actually by copying the source of primefaces they closed the door of their company!
    They made a big mistake and they will see it’s result in near future!!
    If I were a ICE faces user I would switch to Primefaces ASSAP !
    Because that way I’m sure that I’m using the library made by an INNOVATIVE company.

    • I think that’s not entirely true.
      We are using primefaces from the beginning and we think its a fantastic library!
      BUT
      Since the beginning we are missing some very essential functionality to create REAL business applications. Sure, PF has the best showcase on the planet, but e.g. they never managed to create a USABLE data table.
      (Remember, data tables are the most basic and important component of any business application)

      If IceFaces steps in, uses PF datatable source and creates one that really works for REAL WORLD users, we would be very happy!

      • ‘Sure, PF has the best showcase on the planet, but e.g. they never managed to create a USABLE data table.’

        Wow, did he say that ‘PrimeFaces’ never managed to create a USABLE datatable? How many hundreds and/or thousands of web apps are RELIABLY USING PrimeFaces dataTable? I, for one, am RELIABLY USING PrimeFaces dataTable, and I am very pleased.

        • Sorry, but i can not agree!

          Use case:
          1) Viewscoped Datatable is displayed
          2) User: sorts and filters the datatable, clicks a row and is redirected to a page with a detail view
          3) User: clicks some kind of ‘back’ button
          4) Datatable is in default state -> bad user experience

          Maybe I am missing something, but I am sure at the moment it is not possible to implement some kind of data table state recovery with a viewscoped bean behind it.

          I even think it’s not possible with a session scoped bean behind the data table.

          Thats my opinion!
          Greetings
          Karsten

        • I agree that IceFaces strategy is unacceptable.
          But I also agree that p:datatable is under-accentuated in Primefaces. In times far away I used Delphi and bought http://www.woll2woll.com/InfoPower.html just because of it’s powerful datagrid component.
          At least there should be a example in the showcase showing a LazyDataModel combined with sorting, filtering and paging.
          Extracting the information about sorting and filtering on the server side should be demonstrated.
          I will watch the forum for this topics.

          Thank You for Your work on Primefaces
          Dieter Tremel

  22. I think Great news for Primefaces. Now you have ICESoft as your client. Now they are Primefaces follower.

    They can steal the code but can’t steal the brain. They will not use their brain and wait for your innovative ides. Without any new innovation no one will refer Icefaces. They are clearly shame less writing we are referencing the code for Primefaces. So always people will look for parent one.

  23. I had not even heard or primefaces but have been using icefaces for years, now I know about primefaces and will likely use primefaces in the future as well as icefaces. I think the idea of open source is to share and give credit. ICEFaces gave credit to Primefaces for using something Primefaces shared. If you don’t want to participate in open source then close your source and just sell your product like IBM or one of the other vendors. If you make the best product you will get business consulting and supporting businesses who use your product. Just keep doing good work and sharing it and if others use your work great, it means more exposure for you and more potential customers that will come to you. The only thing giving me pause now from diving into Primefaces is the bitterness that is displayed here over the reuse of your open source offering. Would you rather it be a paid product that everyone has to pay you to use? Do you feel as though ICESoft did not give enough credit to you? what is the deal?

  24. Pingback: ICEFaces just a copy of PrimeFaces? | techscouting through the java news

  25. icesoft is shameless, is the same components, not even one enhancement. I moved out icefaces since 2010, best decision ever. primefaces rocks!

  26. That’s really a shame! And I also think this is a death of IceFaces. Copy is already too old and doesn’t include new stuff. Real thing is much better. We see new features day by day. Poor IceFaces, nobody will use you…

  27. I was first shocked when I got the news about this and I was not very happy about it. Even if open source is open by essence which means everybody can use it, copy it, rebuild it as they want (and Prime does the same with JQuery for example) credentials should always return to the code owner. As I never really liked given info and comments without verifying myself and make my own opinion, I went to check the ICEfaces codes myself. Well I had a big surprise when I opened the Accordian component as an example and read the first line:
    “Original Code developed and contributed by Prime Technology.
    Subsequent Code Modifications Copyright 2011-2012 ICEsoft Technologies Canada Corp. (c)”
    So I am now even more shocked to see that nobody checked the info before putting any comments on here just assuming it is the truth. I am not defending one against the other, I am defending the right to have a good and reliable information, not a hoax. Such an attitude is bad for all the Open Source community. Today assuming it is the truth and spreading it over the net discredits ICEfaces. Tomorow the truth is different and credentials to Primefaces are in fact on the components code from ICEfaces …. does it make Primefaces a liar.

  28. IceFaces would not need to change their license to embed Apache 2 licensed code. This is not a requirement of the ASL. If they did so, it was an unrelated choice. Just like Oracle literally takes “Red Hat Enterprise Linux” and changes the branding to “Oracle Unbreakable Linux”

    Welcome to OSS, this shit happens.

  29. Icefaces is despicable. I don’t think that icefaces will ever be truly popular because they are too driven by money and not passion hence stealing code. If you pay for support, they will you make bug fixes available. If you don’t pay, they will not make the current bug fixes available until the next release of bug fixes.

  30. Hi all
    My two cents. Don’t get wrong I really like Primefaces and the work that has been done. You guys have moved the JSF world forward with the integration of top-class JavaScript components. However, stating that “IceSoft copied PrimeFaces code LINE BY LINE to come up with its new set of components” I find is a little hypocritical. You can’t tell me that this Primefaces component hasn’t been copied “LINE BY LINE”.
    http://www.primefaces.org/showcase-labs/ui/schedule.jsf
    See the “orginal” here: http://arshaw.com/fullcalendar/
    Yeah sure you have ‘enhanced it’, but anyone one who has not seen it before would assume you guys developed it. I don’t see any public credits given to the original author on your demo site or in your user manual and I’m sure there are many other examples. The irony is that Primefaces would have never existed unless ‘your’ code had not been copied from some other open source project “LINE BY LINE”.

    • Knuckle you miss the point here, we “link” to 3rd party work when we use, we do not copy the code, change the package names. There is a big difference between linking to open source code at compile time and copy-paste it with renamed packages.

      So you can also copy the PF code, change org.primefaces to org.knuckle and release KnuckleFaces, try to sell commercial support then.

    • Knuckle ,I’m only a jsf favourator , I think you have said is not fair! As a jsf devolper , packing js libaray is common if you are permited. This is a way to let more people to use your libaray .You can know this from Richfaces ,openfaces and event oracle ADF faces ! I think primefaces is correct .Maybe What primefaces need to enhance is to let everyone know clearly abuot the orginal devolper of javascript libaray ! They are also the hero! Optimus Prime ,I think you can write a blog to thank the back hero and tell you clients about the the hero. This is the real meaning of open-source .

  31. For the record, It has been stated here that the ICEfaces ACE components were “90%” copied from PrimeFaces, with no code changes other than package names and no clear enhancement of the components.

    These representations are misleading and untrue. Out of a total of 41 ACE components included in ICEfaces 3:

    - 13 have NO PrimeFaces ancestry or code whatsoever
    (ace:animation, ace:dateTimeEntry, ace:excludeFromExport, ace:sliderEntry, ace:tabSet, ace:tabPane, ace:tabProxy, ace:fileEntry, ace:checkboxButton, ace:commandButton, ace:linkButton, ace:panelExpansion, ace:tableConfigPanel)

    - 19 were PrimeFaces sourced and have received substantial enhancements and bug fixes (ace:ajax, ace:accordion, ace:accordionPane, ace:dataTable – completely re-implemented, ace:cellEditor, ace:column, ace:columnGroup, ace:expansionToggler, ace:row, ace:rowEditor, ace:rowExpansion, ace:dataExporter, ace:dialog, ace:menu, ace:menuBar, ace:notificationPanel , ace:panel, ace:progressBar, ace:tooltip)

    - 9 were PrimeFaces sourced and integrated with the ICEfaces ACE environment (ace:contextMenu, ace:menuButton, ace:menuItem, ace:submenu, ace:draggable, ace:droppable, ace:resizable, ace:maskedEntry, ace:printer)

    In addition, during the course of ICEfaces 3.0 development, there have been several hundred ACE-related code-commits to the SVN repository, and over 200 ACE component JIRAs resolved relating to bugs and feature enhancements (improvements). Many of these JIRAs were generated as a result of extensive automated and manual QA processes that were applied to the new components. Interested parties need only inspect the actual components in the download bundles or our [url="http://sventon.icefaces.org/svn/repobrowser.svn?path=%2ficefaces3%2ftags%2ficefaces-3.0.0&revision=HEAD&name=repo"]SVN repository[/url] to confirm the obvious differences.

    • Ken so you say in total 28 components out of 41. We don’t see any significant enhancements or quality improvements as you mentioned other than changed package names. Believe me, we know the code we’ve written, it is the same.

      While you are here, may I ask why you have done this at all instead of creating your own code, this is what people expect from a JSF component suite vendor. For example why haven’t you wrap the jquery widgets with your own code? What was the reason of copy-paste of PF code with package rename?

      Now do you realize that? Your company is offering commercial offerings based on our work and gets hidden behind the protective walls of open source?

      I’ll make sure that everyone who is evaluating IceFaces will know about what you have done!

      • Also sliderEntry and dateTimeEntry is same although you’ve stated that it has no PrimeFaces origin. So the numbers go up as we check more Ken. So two more.

  32. Plagiarism ! Complete unethical and harmful to open source community. Taking credits from others works is EVIL !

  33. Besides fairness and legitimation of code coping there are other aspects to be discussed. I wanted to write a post in the ICEFaces forum but they locked the thread from Cenk. Well. Ken, you know that the code you copied doesn’t have new re-designed features like attachable ajax events, widget factory, integration with dynamic includes, etc., etc. You have mentioned other advantages of IceFaces in comparison to PrimeFaces. You have said Direct-to-DOM rendering, Ajax Push and Window scope are your power features. But Ken, to be honest, Direct-to-DOM rendering is a performance killer in large web apps. Everybody knows that. Ajax Push is not a big feature. I shown in my blog how it’s easy to integrate JSF and Atmosphere framework together. Also other Server Push frameworks and techniques can be used in JSF directly, without IcePush. And do we need IceFaces for Window scope only? No. I prefer CODI which has Window scope as well.

    Just one question at the end. You probably know how fast PrimeFaces development is going on. We also have a community driven PrimeFaces Extensions project now with the aim to popularize PrimeFaces infrastructure and bring new stuff missing in other libs. We have CKEditor, CodeMirror, Timeline, BlockUI, MasterDetail, …. Do you plan to copy the code from the PF Extensions project? Please stop this wrong way of development. You see the reaction of that action. This way will not increase your popularity.

    Thanks for attention.
    - Oleg.

  34. Many thanks Cenk, but they have deleted the topic. I get “The topic you are trying to see does not exist.” Don’t matter. I think, they have already recognized what they messed things up. I will delete my account by IceFaces (don’t need it anymore). Alone forums are not comparable. Low activities in Ice und high activities in Prime.

  35. I don’t see the big deal. PrimeFaces chose an Apache license, not GPL or LGPL. That’s just how an Apache license works. There is no obligation to give back. If you want to get contributions back, use GPL or something like it.

    Look at Android. Amazon takes the Android code, beats it into submission for Kindle, doesn’t make any effort to give back to the community, and that’s a-ok. I wouldn’t boycott Amazon for that.

    • I don’t think Amazon and Android are competitors Cay. The point we want to emphasize is moral not legal. Our complaint is a competitor of PrimeFaces doing this. Everyone who disagrees with us have the same point of view which is the legal point of view, you as well. We just want to spread the word that anyone evaluating IceFaces is aware of this fact. That’s all!

    • @Cay IceSoft sells commercial services and makes IceFaces ACE code to look like their own saying they have made enhancements, significant code changes to make it “enterprise ready”. Their purpose is not to contribute back to the community but make money from our efforts. This is not right no matter what the license is.

  36. Hi i’ve been using icefaces long time ago but hten i have found the prime. Simplicity, huge amount of new compoments etc. And i just moved :) and I will never come back to ice anymore!

  37. Though it is a custom to follow the leader, it need not be a direct copy of the code without providing major additional features.

    I cannot comment much as I never downloaded ICEFaces even for evaluation purpose.

  38. Really surprised, a well known company is doing just like student copies assignment of others.
    It simply ruined the competition, competition always brings new ideas and things from inside room to outside world.

    We have started social campaign to let tech people IceFaces is just a lame and no creative work.

    Thumbs Up! for Primefaces.

  39. So, the brand new version of icefaces is the old version of Primefaces?
    Big Deal!!
    This is the best reason to choose Prime.

    Guys, you must be proud of yourselves. This means that you are the reference in JSF

  40. Did “CashFaces” buy Enterprise support already? They should. Quality of their product depends directly on PrimeFaces.

  41. I’m using PrimeFaces from version 2.x for a few years. I have also used several other JSF implementations, but neither of them come even close to Prime!

    On this IcyFaces issue: I hope Optimus Prime will have his revenge! :-)

  42. “Our posts and posts of many PrimeFaces users in IceFaces forums has been deleted by IceSoft. Free Speech!”

    Really??? Well, free speech is in the constitution of the United States of America, but is it a part of IceFaces world/realm? (smiling/lol)

  43. I didn’t read all comment on this blog post but here what I can say… there’s a dictate in Brazil, a Brazilian dictate that is similar like this:

    “Na vida nada se cria, tudo se copia!” (in portuguese)
    “In life nothing is created but is copied” (translation not using google)

    But PF is pretty much cool then other component’s suite I’ve ever seen!

  44. Classic example where a little cooperation could have benefit everybody, but instead, both companies choose to compete, copy from each other and point fingers.
    If Instead of wasting time and energy creating identical components you would join forces to get the strength of each package and make them work together, everybody would be happy.
    Shame on both of you “prime-ice” !!! you shamed the open source idea.
    Very disappointed,
    Tamir

  45. Copy past … but sell product and support under icefaces cover… this is stealing of somebody else work. I will never use iceface for my software projects.

  46. Optimus, why wouldn’t you change your license to LGPL? I suppose that in this case you will be restricted in use of Apache licensed software inside PF, but may be I’m wrong..?

    As of subject: I tried all three leading frameworks: Richfaces, Icefaces and Primefaces, can say that Icefaces is the weakest one, it was too heavy, slow and had poor component library. PF is the best one though JSF itself has lots of shortcomings and PF is the only reason why web development using JSF can be successfull.

    Good luck PF team!

  47. Pingback: PrimeFaces 3.1.1 Released |

  48. Dear Community don’t forget to add @PrimeFaces logo to your projects. If you don’t, don’t be surprised when you see yourself in the list of who uses @icefaces. :(

  49. I don’t get it. You are angry, while somebody did something, what you have permitted(via your license). Technically, we all should be careful to use your product. Someday you could claim that we steal your code.

      • The point is, you should be even happy that your rivals copy your code. It should be an advertisement spot for you: “Even rivals use primefaces”. Instead of piss of you should use this as an advantage, just stay cool ;)

        On the other hand, there is still an ethical issue, that they didn’t mention that they use primefaces as base for their components at the first place. And I don’t think that it was an easy decision to use the code of a rival.

        İyi çalışmalar

  50. “…. Future development of ICEfaces components will focus on ACE rather than ICE. The ACE Components will continue to evolve rapidly,…..”

    This sentence should be as this:

    ….. Future development of ICEfaces components will focus on PrimeFaces rather than ICE.The ACE Components will continue to evolve rapidly,…..

  51. That forces me to just throw away whatever interest I had for IceFaces. Primefaces is driven by passion and huge dedication, no one can steal that from Primefaces.

  52. IceSoft: takes code from competitor, renames it sells it as their own, doesn’t inform anyone. Legal: Yes. Ethical: No.

    Business relationships are complicated, and the law can only protect you so much. The most powerful tools in your arsenal is trust and ethics. IceSoft has proven they are both unethical and can’t be trusted. What they did might be ‘legal’ but hey so is prostitution in some areas.

    Way to be, Primefaces Team. And thanks for being such good chaps about it. “Hate it or love it the underdog’s on top. And I’m gonna shine homie”

  53. To say that “IceFaces Copies PrimeFaces Line by Line” is quite a stretch. Shame on you for making such a misleading and inflammatory statement to your community! And shame on the people who ignorantly parrot this without doing their homework. Ah well, such is the Internet. People read something and take it as the truth and then spew it out to the world. People, do your homework. You took a few examples of components that were not changed by Icesoft and make this claim: “We have looked in detail of all IceFaces Ace Components and more than 90% of IceFaces components are like Panel. They are copied line by line, only difference is the change of package names from prime to ice. This duplication applies to java renderers, components codes, javascripts and css files as well.” Sometimes it is nice to have an independent look at things without the bias of an angry perspective. How about you put examples of ALL of the ACE components in ICEfaces and compare them with PrimeFaces? Your 90% claim would then just be a lie, or at best a wild fantasy. Any good developer should be shocked that a “detailed” review was done in such a shoddy manner. Would you apply the same ethics to your consulting practice?

    Here is another wild claim “IceFaces has lost significant of it’s user base to PrimeFaces since 2009 and they are trying to get their popularity back”. Where is your source for this “amazing” fact? Do you know in fact how many there are in the IceFaces user base? What to you is a significant number? How do you think you can create any credibility with this nonsense? Are you basing this on the Google search for the product names? How silly. Here are some interesting statistics – on the PrimeFaces forum total members 10957, and on the ICEfaces Forum 143,448. Quite a big gap. If you just looked at that comparison you could conclude that ICEfaces is definitely the market leader. But of course that would just be one perspective and wouldn’t validate your case.

    Your hypocritical comment is laughable “…which is copying our code line by line and offer commercial services like support, consulting and training over our copy-paste code.” Prime does this as does every other open source software company. If you weren’t deriving revenue from support and consulting yourselves there would be no PrimeFaces. That is why there are open source software licenses. How naïve of you to think that if you build something that someone else wants to use in a commercial effort that they wouldn’t do that. Do you call all of your customers thieves? And to add insult to injury you make it sound like all of ICEfaces was copied from PrimeFaces. Obviously you don’t like to let the truth interfere with a good story. You were certainly successful in riling up a few of your PrimeFaces supporters with your twisted and sad dialogue. It occurs that your anger is really based on a fear of the future of PrimeFaces and that you could all possibly become redundant. My opinion is that folks who attack their competition with untruths and partial truths to make themselves look like good guys and martyrs are only diminishing themselves and what they have accomplished. You have been successful to a point, why don’t you take all that energy that you have been putting into attacks and continue to build your business. Trust me; you can’t give your business 100% when you’re spending time and effort on these types of attacks. If you want to play in the open source world then accept all that comes with it without all the rhetoric. Sure, Icesoft maybe could have done a better job of giving Prime credit, but that is what it is, and it does look like they responded positively to the community feedback in ensuring that due credit has been given. It still doesn’t diminish PrimeFaces in any way.

    I must admit I’m also somewhat biased. My company (a large European financial institution) looked at several technologies including PrimeFaces before choosing ICEfaces. We really didn’t see PrimeFaces as a complete solutions after doing initial prototyping and testing. We had requirements for large scale deployment with thousands of users with a need for reliability and high performance. We have had great results and are very happy with our choice. We particularly appreciate the continued efforts of Icesoft to innovate and evolve ICEfaces over the years. Thanks to all the ICEfaces developers for their hard work and dedication. We really appreciate it. I think it is time for them to be recognized for creating an amazing project. Also big kudos to Icesoft for taking the high road in this issue and not lowering themselves to the verbal tirades seen here. That says a lot!

    My final word to Prime – don’t undo all the success you have had so far in creating PrimeFaces by continuing this crazy bitching! It is a testament to your work that Icesoft wanted to include your work in their popular ICEfaces project.

    • Dear Jeff,

      IceFaces forum has 143000 users as claimed, it is easy to get that many users with a bad spam detection. User activity is very low, post count is 60511 so there are 83000 users who didn’t post anything, does it make sense for you? In PrimeFaces forum we have 10000+ users with post count close to 60000 so everyone has made around 5 posts in average. PrimeFaces is 4 years younger than IceFaces and post count is same.

      If you have requirement for large scale, IceFaces is definitely the wrong choice as every experienced JSF developer knows the D2D is hard to scale. That’s why the new Ace components of IceFaces follow the approach of PrimeFaces which is lightweight.

      I think your reaction is understandable as you have chosen IceFaces and not everyone likes to admit they have made a wrong decision.

      IceFaces is currently powered by PrimeFaces so your application if you move to new version of Ice will also be powered by PrimeFaces. IceSoft also states it at;

      http://www.icesoft.org/projects/ICEfaces/components.jsf

      So although I don’t agree with you, we’ve accepted your comment due to respect to everyone’s opinion.

    • You didn’t see Primefaces as an enterprise solution but the company behind ICEFACES saw that and copied the sources!!!
      Ha ha ha !!!
      All topics related to this discussion located in ICE’s forum are locked or deleted !!! Ha ha ha !!!
      This is freedom and this is respect to community and this is open source that we are learning from ICESOFT !

      Primefaces is really great.
      When I wanted to choose a JSF component set I almost tried all existing component libraries but to be honest Primefaces is something else!
      Have a wonderful time ;)

  54. So,
    PrimeFaces 2 –> Icefaces 3
    PrimeFaces 3 –> Icefaces 4
    PrimeFaces 4 –> Icefaces 5
    PrimeFaces 5 –> Icefaces 6
    … etc
    hehehe :-)

  55. Always been a fan primefaces, been recommending it in projects, this only reaffirms that primefaces is the best jsf library

  56. Pingback: Final Words on PrimeFaces Fork |

  57. Just a guess, but I believe they copied Primefaces because their product was a failure and they knew they’d been outdone. I’ve attempted to use icefaces on two projects in the past and both times was bitterly disappointed. Icefaces was buggy and slow both times, never again…