# JSF: Hyperlinks reagieren nicht



## MichiM (16. Feb 2008)

Hallo,

wieder mal ein JSF-Projekt - Woran kann es liegen, dass die Hyperlinks keine Wirkung zeigen?

*Code-Auszug:*


```
<f:view>
                        
                        <h:form>
                            <h:commandLink id="p1" action="punkt1" value="Punkt1" />
                            <h:commandLink id="p2" action="punkt2" value="Punkt2" />
                        </h:form>
                        
                    </f:view>
```


(Es handelt sich hierbei um inkludierten Code, spielt das evtl. eine Rolle?)


*faces-config.xml:*


```
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN" "http://java.sun.com/dtd/web-facesconfig_1_0.dtd">
<faces-config xmlns="http://java.sun.com/JSF/Configuration">

  <navigation-rule>
    <navigation-case>
      <from-outcome>punkt1</from-outcome>
      <to-view-id>/punkt1.jsp</to-view-id>
       <redirect/>
    </navigation-case>
  </navigation-rule>  

  <navigation-rule>
    <navigation-case>
      <from-outcome>punkt2</from-outcome>
      <to-view-id>/punkt2.jsp</to-view-id>
       <redirect/>
    </navigation-case>
  </navigation-rule>  
  
</faces-config>
```

(Die Rules sollen für alle Seiten gelten, deshalb keine Angabe "from-view-id".)


*web.xml:*

```
<?xml version="1.0"?>

<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-app_2_4.xsd"
    version="2.4">

	

  <servlet>
    <servlet-name>FacesServlet</servlet-name>
    <servlet-class>
      javax.faces.webapp.FacesServlet
    </servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet> 

  
  <servlet-mapping>
    <servlet-name>FacesServlet</servlet-name>
    <url-pattern>*.jsf</url-pattern>
  </servlet-mapping>
  
    

</web-app>
```


Gruß Michi


----------



## Guest (17. Feb 2008)

Hallo,

also ich bin der Meinung, dass bei globalen Naviregeln ebenfalls die Angabe von _from-view-id_ notwendig ist. Damit die Naviregeln dann auch global wird, müssen natürlich Wildcards benutzt werden.

Globale Regel für die ganze App


```
<from-view-id>*</from-view-id>
```

Lokale Regel für einen Teilbereich


```
<from-view-id>/unterordner/*</from-view-id>
```

Ich weiß jetzt nicht, obs nur daran lag da ich mir das ganze nicht im Detail angeschaut hab. Mir ist nur beim überfliegen deines Beitrags aufgefallen, dass du from-view-id explizit weglässt.

Gruß


----------



## MichiM (17. Feb 2008)

```
<from-view-id>*</from-view-id>
```

hab ich jetzt nochmal eingebaut, funktioniert dennoch nicht...


Was kann denn in den paar Zeilen XML jetzt schon wieder so falsch sein?

Gibt es eine Möglichkeit, diese Navigationszuweisungen innerhalb JSF über ein Tool (evtl. in NetBeans-Umgebung oder zum Nachinstallieren) auf Stimmigkeit prüfen zu lassen?


----------



## Reeny (18. Feb 2008)

Ich würd an deiner Stelle auch statt


```
<h:commandLink id="p1" action="punkt1" value="Punkt1" />
```

das eher so schreiben:


```
<h:commandLink id="p1" action="#{Bean.punkt1}" value="Punkt1" />
```

Dein Bean muss dann natürlich auch eine parameterlose Funktion haben, die ein String zurückgibt (für die Navigationsregeln).


----------



## freez (18. Feb 2008)

@Reeny: das sehe ich anders. Sowas mache ich nur, wenn ich die Navigation mit der Bean beeinflussen will. Habe ich aber eine sture Regel, dann gebe ich den text direkt an.

@MichiM: Ich habe spontan keine Idee, warum deine Navi nicht geht. So einfache Sachen würde ich mit einem outputLink auf die entsprechende Seite realisieren (nur mal so als alternativen Lösungsweg)


----------



## Reeny (18. Feb 2008)

Oh, hab die Absicht von _MichiM_ nicht verstanden.

Sorry


----------



## freez (18. Feb 2008)

@MichiM: was heist "inkludierten Code" bei dir?


----------



## number8 (18. Feb 2008)

Also ich hab das ganze mal schnell in NetBeans aufgesetzt und der linkt punkt1 springt auch auf die seite punkt1.jsp.


----------



## maki (18. Feb 2008)

Hast du noch irgendwelche Felder in der JSP, welche die zufällig validiert/konvertiert/nicht leer sein dürfen?
Irgendwelche Messages?

FacesTrace kann bei so etwas sehr nützlich sein.


----------



## number8 (18. Feb 2008)

Ah, dem pflichte ich bei. Ein fehlendes Message-Tag kann viel Ärger besdeuten, da man 
for( ; ; ) {
sucht und 
}


----------



## Guest (18. Feb 2008)

@number8

Kannst du da bitte n bissl ausholen, was bei dir ein fehlender Message-Tag ist? Ich frag deshalb, weil ich bisher noch nirgends gelesen hab, dass dies eine Pflichttag für Formulare in JSF ist. Hast du da zufällig Quellen zu? Würde mich sehr interessieren, was da für Fehler durch weglassen der Message-Tags entstehen können 

@Reeney

Der von dir beschriebene Umweg über eine Methode einer Managed/Backing Bean ist nur erforderlich, wenn man eine dynamische Navigation benötigt, was in diesem Fall nicht gegeben scheint. Für statische Navigation ist der Ansatz von MichiM genau richtig.

@Freez

Das direkte Ansteuern von absoluten/relativen URLs aus den JSF-Seiten ist grundsätzlich nicht zu empfehlen. Man verlagert die Navigationslogik aus der faces-config aus und verteilt sie an verschiedene Stellen in der Anwendung. Die Wartbarkeit leidet unter so einem Programmierverhalten enorm, was spätestens bei großen Webanwendungen zu einem kritischen Faktor werden kann. Zudem spricht MichiM von globalen Navigationsregeln. Daher kann man davon ausgehen, dass er die besagten Links in mehreren Seiten einbinden möchte (z. B. ein globaler Link auf allen Seiten zu einer Loginseite). Sollte sich jetzt jemals der Pfad zu besagter Seite verändern, müsste nach deinem Ansatz auf jeder Seite die Pfadänderung nachgepflegt werden. Mittels dem von JSF vorgesehenen zentralen Ansatz reicht es aus, die Pfadänderung an einer Stelle zu ändern (bei statischen Naviregeln in der faces-config, bei dynamischen u. U. evtl. noch die Methode der Managed Bean).

@MichiM

Ich würde number8 auch zustimmen, dass bei dir irgendwas anderes wohl verantwortlich ist. Alle jars in der richtigen Version dem Projekt hinzugefügt? Werden die auch beim Deployment mit auf den Appserver/Servlet container übertragen? Was sagt das Logfile deines Servers? Was passiert, wenn du ein blank-Projekt von JSF nimmst, und deinen Code dorthin überträgst?

Grüße


----------



## maki (18. Feb 2008)

> Kannst du da bitte n bissl ausholen, was bei dir ein fehlender Message-Tag ist? Ich frag deshalb, weil ich bisher noch nirgends gelesen hab, dass dies eine Pflichttag für Formulare in JSF ist. Hast du da zufällig Quellen zu? Würde mich sehr interessieren, was da für Fehler durch weglassen der Message-Tags entstehen können icon_wink.gif


Bin zwar nicht number 8,

aber stell dir vor es gibt einen Fehler, und keiner merkt's, dafür wundert man sich warum "es nicht weitergeht".


----------



## number8 (18. Feb 2008)

Ja stimmt, das war etwas konfus, aber im Prinzip hat mein Vorredner ja das Wichtige schon gesagt.


----------



## MichiM (18. Feb 2008)

Hallo,

dass es zunächst nicht ging, lag wohl am Inkludieren.

Setz ich die JSF-Hyperlinks in eine simple JSP, gehts.



> <%@page contentType="text/html"%>
> <%@page pageEncoding="UTF-8"%>
> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
> <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
> ...



Nun reicht aber eine simple JSP bei meinem gewählten Ansatz nicht.

Mein Ansatz:

basis.jsp enthält fixen Rahmenteil des "Portals"

Die dynamischen Teile werden über die basis.jsp jeweils inkludiert.

Sieht so aus:

Link auf Punkt1 -> punkt1.jsp übergibt der inkludierten basis.jsp die Parameter,
damit der entsprechende Content eingebettet wird

Beispiel:

start.jsp:


```
<?xml version="1.0" encoding="UTF-8" ?>
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<% String  seite = "0"; %>
<%@ include file="basis.jsp" %>
```

basis.jsp


```
<%@ page language="java" %>
<%@ page import = "java.io.*" %>
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>

<%--

hier ein kleines Skriplet, das in Abhängigkeit von der Variablen "seite" die entsprechenden Daten für
die zu inkludierende Unterseite für den dynamischen Bereich bereitstellt, das wären neben
Seitentitel, Metatags, etc. vor allem auch der Name der JSP

--%>

    <html xmlns="http://www.w3.org/1999/xhtml"
  lang="de" xml:lang="de">

    <head>
    
        <title>
            <%= title %>
        </title>

...


                    <f:view>
                        
                        <h:form>
                            <h:commandLink id="p1" action="punkt1" value="Punkt1" />
                            <h:commandLink id="p2" action="punkt2" value="Punkt2" />
                        </h:form>
                        
                    </f:view>

...


                        <f:view>

                              <f:subview id="subview">
                                  
                                    <jsp:include page="<%= dynamischer_teil %>" />

                              </f:subview>
                          
                        </f:view>


    </body>

</html>
```

In der PHP-Welt sind solche Schemen recht geläufig, denk ich, nun weiß ich aber nicht, wie es da in der
Java-Welt aussieht, insbesondere beim Einsatz von JSF. :wink:

Was ich natürlich nicht schön fände, wäre, um die dreiundachtzig mal den fixen Rahmenteil einer Seite in die ganzen
Unterseiten mit reinzupacken, wie das vor rund 10 Jahren noch gemacht werden musste, als Skriptsprachen noch nicht
verfügbar waren. Was ich auch nicht unbedingt - vor allem wegen der Übersicht in dieser einen Datei, weiterhin wegen
der Dateigröße - mag, wäre, die ganzen dynamischen Inhalte in eine JSP zu packen und je nach URL-Parameter den
entsprechenden Teil einzubinden o.ä.

Am Liebsten wäre mir also schon der o.g. Ansatz.

*Problem hierbei:* Sobald sich die JSF-Hyperlinks in einer inkludierten basis.jsp befinden, funktionieren sie nicht
mehr, so zumindest das vorläufige Ergebnis meiner Problemanalyse, wobei natürlich nicht auszuschließen ist,
dass beim Inkludieren was Wichtiges vergessen wurde oder dass es anders sowieso schöner geht usw. :wink:

* Womit hat das zu tun, dass JSF-Hyperlinks in einem inkludierten Bereich nicht mehr mögen, obwohl für die
Navigation Rules ja durchgehend definiert wurde:


```
<from-view-id>*</from-view-id>
```

* Ist der o.g. Ansatz zum Aufbau von JSF-Anwendungen (bei reinen JSP-Seiten funktionierts ja einwandfrei)
mit einem großflächigen fixen Rahmenteil geeignet oder wer kennt einen Link mit einem hübscheren Ansatzbeispiel?

Gruß Michi


----------



## Guest (18. Feb 2008)

@maki

Dann hab ich number8 und dich wohl Missverstanden  Wenn natürlich ein Validator nen Fehler ausgibt, dann ist es klar, dass es nicht weiter geht. Ich dachte ihr meintet davon losgelöst könnte es evtl. noch Fehler geben 

@Michi

Was spricht gegen die Verwendung von Facelets?


----------



## MichiM (18. Feb 2008)

> Was spricht gegen die Verwendung von Facelets?



Direkt dagegen spricht nichts, außer, dass es bisschen viel Umstellung auf einmal ist und dass Facelets noch nicht so richtig anrollen (muss man im Moment ja eh noch separat dazubasteln), kommt aber bestimmt noch mit den nächsten Versionen, wenns mit JSF fusioniert, bis dahin begibt man sich (mal wieder) auf relativ einsame Pionierpfade (gibt ja bisher auch kaum Doku und Forenstoff dazu), geht nur, wenn man viel Freizeit hat.  :wink:


----------



## freez (19. Feb 2008)

Das würde ich nicht behaupten. Templating mit Facelets ist gar nicht so schwer und ich habe auch ein Projekt innerhalb recht kurzer Zeit umgestellt gehabt. Alternativ würde ich Tiles empfehlen. Funktioniert auch recht gut.


----------



## SnooP (20. Feb 2008)

Man darf in ein view-Element nichts einfach so inkludieren wie schon festgestellt wurde - gehen tut das aber trotzdem mit den entsprechenden subview-Tags. Problem ist da der Komponentenbaum, der durch eine simple JSP-Include-Derektive durchbrochen wird... wenn man nur JSP verwendet, dann funktioniert die Sache genau wie in php auch - aber bei jsf muss man halt doch mehr Hintergrundwissen haben...

Letztlich ist Facelets und auch Tiles fürs Layouting sehr gut geeignet... - Tiles würde ich aber nur verwenden, wenn man das von anderen Frameworks her kennt, wie etwa aus struts - Facelets bietet einfach noch ein wenig mehr.


----------



## MichiM (21. Feb 2008)

Warum die JSF-Hyperlinks nicht funktioniert haben, hab ich nun durch ein wenig Probierarbeit ebenfalls rausgefunden:

In jede Haupt-JSP (wenn sie auch nichts anzeigen, sondern z.B. nur die Parameter für die Basis-JSP festlegen soll) muss bereits


```
<f:view>
</f:view>
```

enthalten.

Damit wäre dieses Problem schon mal gelöst.


(JSF-konforme Einbindung von Unterseiten probier ich demnächst nochmal aus, wie ich dazukomme. :wink: )


----------



## MichiM (25. Feb 2008)

Nun also zu den Unterseiten...


*Versuch, eine simple Portalstruktur mit JSF aufzubauen*

Mal ein komplettes Beispiel:


faces-config.xml:

```
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"
"http://java.sun.com/dtd/web-facesconfig_1_0.dtd">
<faces-config xmlns="http://java.sun.com/JSF/Configuration">

  <navigation-rule>
    <from-view-id>*</from-view-id>
    <navigation-case>
      <from-outcome>seite1</from-outcome>
      <to-view-id>/seite1.jsp</to-view-id>
      <redirect>
      </redirect>
    </navigation-case>
  </navigation-rule>  

  <navigation-rule>
    <from-view-id>*</from-view-id>
    <navigation-case>
      <from-outcome>seite2</from-outcome>
      <to-view-id>/seite2.jsp</to-view-id>
      <redirect>
      </redirect>
    </navigation-case>
  </navigation-rule>  
  
</faces-config>
```


web.xml:

```
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <context-param>
        <param-name>com.sun.faces.verifyObjects</param-name>
        <param-value>false</param-value>
    </context-param>
    <context-param>
        <param-name>com.sun.faces.validateXml</param-name>
        <param-value>true</param-value>
    </context-param>
    <context-param>
        <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
        <param-value>client</param-value>
    </context-param>
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
        </servlet>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.jsf</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <welcome-file-list>
	<welcome-file>
            index.jsp
        </welcome-file>
    </welcome-file-list>
</web-app>
```


index.jsp:

```
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>

<% response.sendRedirect("/jsfportal/seite1.jsf"); %>
```


seite1.jsp:

```
<?xml version="1.0" encoding="UTF-8" ?>
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<% String  seite = "1"; %>
<%@ include file="basis.jsp" %>
```


dynamisch_seite1.jsp:

```
<h1>Willkommen auf Seite 1, der Startseite des Portals</h1>




Haben Sie viel Spa& beim folgenden Besuch dieses Portals!
```



seite2.jsp:

```
<?xml version="1.0" encoding="UTF-8" ?>
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<% String  seite = "2"; %>
<%@ include file="basis.jsp" %>
```


dynamisch_seite2.jsp:

```
<h1>Willkommen auf Seite 2, einer Eingabeseite</h2>




Kehren Sie zur&ck zur Startseite:

                    <f:view>
                        
                        <h:form>
                            
                                <h:panelGrid border="0" columns="0">
                                    
                                    <h:commandLink id="p1" action="seite1" value="Startseite" />
                                
                                </h:panelGrid>
                            
                        </h:form>
                    
                    </f:view>


Bitte geben Sie hier Ihre Daten ein:

<f:view>

        <h:form>
    
              Vorname: <h:inputText value="" />
              Nachname: <h:inputText value="" />

              <h:commandButton action="success" value="ok" />
    
        </h:form>
          
</f:view>
```


basis.jsp:

```
<%@ page language="java" %>
<%@ page import = "java.io.*" %>
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>

<%

            String  title               =   "";
            int     seiteInteger        =   0;
            String  dynamischer_teil    =   "";
    
            if ( seite != null )
            {
                        if (
                                
                                    ( seite.length ( ) > 0 )
                                    &&
                                    ( seite.length ( ) <= 30 )
                           )
                        {

                               if ( isNumeric ( seite ) )
                               {
                                   
                                   

                                    seiteInteger = Integer.valueOf ( seite ).intValue ( );

                                    switch ( seiteInteger )
                                    {

                                        case 2:     title               = "Seite 2";
                                                    dynamischer_teil    = "dynamisch_seite2.jsp";
                                                    
                                                    break;
                                                    
                                        default:    
                                            
                                                    title               = "Seite 1";
                                                    dynamischer_teil    = "dynamisch_seite1.jsp"; // Startseite
                                    }

                               }
                        }
            }

    %>

    <html xmlns="http://www.w3.org/1999/xhtml"
  lang="de" xml:lang="de">

    <head>
    
        <title>
            <%= title %>
        </title>
        
            <meta name="description" content="Testseite" />
            <meta name="keywords" content="Testseite" />

    </head>

    <body>

        <div width="100%" style="text-align:left">

        <table width="970" border="0" cellspacing="0" cellpadding="0" style="background-color:#ffffaa;margin-top:25px;">

          <colgroup>

            <col width="970" />

          </colgroup>

            <tr>

                <td valign="top" align="left" style="padding:25px;">
                    
                    <h1>
                        JSF-Portal
                    </h1>
                    
                </td>

            </tr>

        </table>
        
        
        
          
        <table width="970" border="2" cellspacing="0" cellpadding="0" style="background-color:#f5f5f0">

          <colgroup>

            <col width="270" />
            <col width="700" />

          </colgroup>
            
            <tr>
                
                <td valign="top" align="left" style="padding:25px; padding-left:40px;padding-bottom:320px;">
                        
                    <f:view>
                        
                        <h:form>
                            
                                <h:panelGrid border="0" columns="0">
                                    
                                    <h:commandLink id="p1" action="seite1" value="Seite 1" />

                                    <h:commandLink id="p2" action="seite2" value="Seite 2" />
                                
                                </h:panelGrid>
                            
                        </h:form>
                    
                    </f:view>

                </td>
                
                <td valign="top" align="justify" class="haupttext" style="padding:24px;">
                    
                    
                    
                    <p align="justify">
                        
                                <f:subview id="subview1">
                    
                                       <jsp:include page="<%= dynamischer_teil %>" flush="true">

                                            <jsp:param name="" value="" />

                                       </jsp:include>
                                       
                                </f:subview>
                        
                    </p>
                    
                    
                        
                </td>
                
            </tr>
            
        </table>
        
        </div>

        
    </body>

</html>


    <%! 
            public boolean isNumeric ( String myInput )
            {
                 if (myInput == null || myInput.length() < 1)
                 {
                     return false;
                 }
            
                 int start = 0;
                 if (myInput.charAt(0) == '-')
                 {
                     start = 1;
                 }
            
                 for(int i = start; i < myInput.length(); i++)
                 {
                     if (!Character.isDigit(myInput.charAt(i)))
                     {
                         return false;
                     }
                 }
                 return true;
            }      
    %>
```


Dieses Beispiel funktioniert mal so weit, dass auf Klicken der Links des Hauptmenüs die zugehörigen Seiten im dynamischen Bereich rechts eingeblendet werden, jedoch ohne JSF-Funktionalität innerhalb dieser Seiten. Hat wohl damit zu tun, dass subview nicht richtig angewendet wird, allerdings hab ich jetzt schon alles Mögliche durchprobiert, auch, dass die JSPs seite1.jsp und seite2.jsp bereits eine leere View eingebettet bekommen, aber schaff es nicht.

Wer kann mir sagen, wo innerhalb dieser beteiligten Dateien noch was an views / subviews / verbatims mit welchen IDs etc. eingefügt bzw. rausgenommen werden muss, damit der interne JSF-Baum nicht unterbrochen wird und die Unterseiten im dynamischen Bereich voll funktionstüchtig werden? :wink:


----------



## MichiM (27. Feb 2008)

Habe das gefunden:

http://balusc.blogspot.com/2007/01/dynamic-jsf-subviews.html

Aber als Fragment hilft es auch nur wieder bedingt. Leider nirgends ein vollständiges halbwegs und reelles Beispiel für ein JSF-Gerüst mit ein paar subviews, idealerweise noch mit variablem Aufruf, und ansonsten ein wenig HTML im verbatim-Teil dazu zu finden. Insbesondere, wenn es um subview geht, ist das problematisch, wenn der Code rausgerissen dargestellt wird...


----------

