<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html"> <h:form> <h:inputText value="test"></h:inputText> <!-- <h:inputText value="yorum içinde"></h:inputText> --> </h:form> </html>Ancak bu sayfa çalıştırıldığında yorum içinde yazılanlar sayfanın kodunda görünecektir. Yorum içindeki hiç bir şey sayfa kodunda gözülmesin istenirse aşağıdaki gibi bir parametre eklenmelidir. web.xml'e aşağıdaki gibi ekleme yapılabilir :
<context-param>
<param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name>
<param-value>true</param-value>
</context-param>
JSF'nin eski versiyonlarında facelets.SKIP_COMMENTS şeklinde kullanılır.
FACELETS_SKIP_COMMENTS eklendiğinde tüm yorumlar gözükmez. Bu durum kod içinde gelitiricilerin yorumlarının da sayfanın kodunun gözükmeyeceği anlamına gelir.
FACELETS_SKIP_COMMENTS yerine ui:remove elementi de kulanılabilir :<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets"> <h:form> <h:inputText value="test"></h:inputText> <ui:remove> <h:inputText value="yorum içinde"></h:inputText> </ui:remove> </h:form> </html>
Aşağıdaki örnekte kullanıcıya google map gösteriyoruz. Kullanıcı marker'ı sürükleyerek istedediği bir konumu seçmesini sağlıyoruz :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
var geocoder = new google.maps.Geocoder();
function updateMarkerPosition(latLng) {
document.getElementById('testform:info').innerHTML = [
latLng.lat(),
latLng.lng()
].join(', ');
document.getElementById('testform:infoLatitude').value = latLng.lat();
document.getElementById('testform:infoLongitude').value = latLng.lng();
}
function initialize() {
var latLng = new google.maps.LatLng(41.00554818815703, 29.036333984374778);
var map = new google.maps.Map(document.getElementById('mapCanvas'), {
zoom: 8,
center: latLng,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var marker = new google.maps.Marker({
position: latLng,
title: 'Point A',
map: map,
draggable: true
});
google.maps.event.addListener(marker, 'dragend', function() {
updateMarkerPosition(marker.getPosition());
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
<style>
#mapCanvas {
width: 400px;
height: 400px;
}
</style>
</h:head>
<body>
<h:form id="testform">
<div id="mapCanvas"></div>
<h:outputText id="info" value="Koordinarlar Buraya Yazılacak" />
<h:inputHidden value="#{testBean2.latitude}" id="infoLatitude"/>
<h:inputHidden value="#{testBean2.longitude}" id="infoLongitude"/>
<h:commandButton action="#{testBean2.submit}" value="Ok" />
</h:form>
</body>
</html>
Java Bean kısmı ise sadece latitude ve longitude şeklinde iki özelliği vardır ve submit edildiğinde bu değerleri ekrana basmaktadır :
@ManagedBean
@SessionScoped
public class TestBean2 {
String latitude;
String longitude;
public String getLatitude() {
return latitude;
}
public void setLatitude(String latitude) {
this.latitude = latitude;
}
public String getLongitude() {
return longitude;
}
public void setLongitude(String longitude) {
this.longitude = longitude;
}
public String submit(){
System.out.println("latitude:"+latitude);
System.out.println("longitude:"+longitude);
return "";
}
}
Google map varsayılan olarak İstanbul ile açılacaktır. Marker drag işlemi tamamlandığında updateMarkerPosition fonksiyonu çağrılacak ve infoLatitude ve infoLongitude hidded form değerleri set edilir.
import java.util.Arrays;
import java.util.List;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;
@FacesConverter(value = "com.fibiler.jsf.converter.ListConverter")
public class ListConverter implements Converter{
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
String[] values=value.split(",");
return Arrays.asList(values);
}
@Override"
public String getAsString(FacesContext context, UIComponent component, Object value) {
List<String> list=(List)value;
String joined = String.join(",", list);
return joined;
}
}
Gelen değer , ile parçalanıp listeye çevrilmekte, ters olarak da gelen liste aralarına , eklenerek birleştirilmektedir.
Aşağıdaki gibi bir bean ve xhtml ile kullanılabilir:
import java.util.ArrayList;
import java.util.List;
import javax.annotation.ManagedBean;
@ManagedBean
public class ListConverterTestBean {
private List<String> items=new ArrayList<String>();
public ListConverterTestBean() {
items.add("ITEM1");
items.add("ITEM2");
items.add("ITEM3");
}
public List<String> getItems() {
return items;
}
public void setItems(List<String> items) {
this.items = items;
}
public void submit(){
for (String string : items) {
System.out.println("item :" + string);
}
}
}
Bu bean aşağıdaki gibi kullanılabilir:
<h:form>
<h:inputText value="#{listConverterTestBean.items}"
converter="com.fibiler.jsf.converter.ListConverter"></h:inputText>
<h:commandButton action="#{listConverterTestBean.submit}"
value="Submit"></h:commandButton>
</h:form>
Görüldüğü gibi converter="com.fibiler.jsf.converter.ListConverter" ile converter verilmiştir.
public enum Test {
ITEM1,
ITEM2,
ITEM3;
}
Bu enum kullanıldığı bean aşağıdaki gibi olsun :
import javax.faces.bean.ManagedBean;
import javax.faces.model.SelectItem;
@ManagedBean
public class EnumBean {
private Test selected;
public Test[] getEnums(){
return Test.values();
}
public SelectItem[] getEnumsAsSelectItem() {
SelectItem[] items = new SelectItem[Test.values().length];
int i = 0;
for(Test t: Test.values()) {
items[i++] = new SelectItem(t, t.toString());
}
return items;
}
public String submit(){
System.out.println("selected value : " + selected);
return "";
}
public Test getSelected() {
return selected;
}
public void setSelected(Test selected) {
this.selected = selected;
}
}
getEnums() ile Enum değeleri dizi olarak verilmektedir. İstenirse getEnumsAsSelectItem() ile de SelectItem listesi olarak alınabilir.
<h:form>
<h3>Enum Test 3</h3>
<h:selectOneMenu value="#{enumBean.selected}">
<f:selectItems value="#{enumBean.enums}"></f:selectItems>
</h:selectOneMenu>
<h:commandButton action="#{enumBean.submit}" value="Submit"></h:commandButton>
</h:form>
Submit düğmesine basıldığında console'de basılan elementin değeri gösterilir.
public enum Test {
ITEM1("item 1"),
ITEM2("item 2"),
ITEM3("item 3");
String title;
Test(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
Eğer açılır listede title değerini göstermek istiyorsanız sayfada aşağıdaki gibi değişiklik yapabilirsiniz:
<h:selectOneMenu value="#{enumBean.selected}">
<f:selectItems value="#{enumBean.enums}"
var="t" itemLabel="#{t.title}" itemValue="#{t}"></f:selectItems>
</h:selectOneMenu>
<dependency> <groupId>java.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.0</version> </dependency> <dependency> <groupId>org.glassfish</groupId> <artifactId>javax.faces</artifactId> <version>2.3.9</version> </dependency> <dependency> <groupId>javax.faces</groupId> <artifactId>javax.faces-api</artifactId> <version>2.3</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.enterprise</groupId> <artifactId>cdi-api</artifactId> <version>1.2<version> </dependency> <dependency> <groupId>org.jboss.weld.servlet</groupId> <artifactId>weld-servlet</artifactId> <version>2.2.9.Final</version> </dependency> <dependency> <groupId>javax.json</groupId> <artifactId>javax.json-api</artifactId> <version>1.1.4</version> </dependency> <dependency> <groupId>org.glassfish</groupId> <artifactId>javax.json</artifactId> <version>1.1.4</version> </dependency>java.lang.ClassNotFoundException: javax.json.Json
import java.io.Serializable;
import javax.faces.push.Push;
import javax.faces.push.PushContext;
import javax.faces.view.ViewScoped;
import javax.inject.Inject;
import javax.inject.Named;
@Named
@ViewScoped
public class MessageBean implements Serializable {
@Inject @Push
private PushContext mypush;
private String message;
public void sendMessage() {
mypush.send(message);
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
mypush, push enpoint'idir. sendMessage() yöntemi çağrıldığında gelen mesaj diğerler sayfalara gönderilir.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>Socket</title>
</h:head>
<h:body>
<h:form>
<script>
function myMessageListener(message) {
alert(message);
}
</script>
<f:websocket channel="mypush" onmessage="myMessageListener"/>
<h:inputText id="pushMessage" value="#{messageBean.message}"/>
<br/>
<h:commandButton action="#{messageBean.sendMessage}" value="Send Message"/>
</h:form>
</h:body>
</html>
Yazı alanına mesajı yazıp Send Message düğmesine basılınca MessageBean'in sendMessage yöntemi çağrılır. Bu yöntemde socket açmış tüm sayfalara mesajı iletir.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns:h="http://java.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>Socket</title>
</h:head>
<h:body>
<h:form>
<script>
function myMessageListener(message) {
alert(message);
}
</script>
<f:websocket channel="mypush" onmessage="myMessageListener"/>
</h:form>
</h:body>
</html>
JSF'de "One or more resources have the target of 'head', but no 'head' component has been defined within the view" gibi bir hata alırsanız view içinde head etiketini h:head olarak değiştirmeniz gerekir.
Bir onay kutusuna tıklandığında sunucuya gidilmesi isteniyorsa aşağıdaki gibi yapılmalıdır :
<h:selectbooleancheckbox id=“approveId" value="#{XBean.xvalue}" onclick="submit();" immediate="true"
valueChangeListener="#{XBean.xValueChangeListener}"/>
Görüldüğü gibi click'leme işleminde form sunucuya gönderilmektedir. Validasyon'a takılmaması içinde immediate özelliği true yapılmıştır.
Sunuc tarafındaki xValueChangeListener fonksiyonu aşağıdaki gibidir :
public void checkedClicked(ValueChangeEvent event) {
// kod
}
<ui:repeat value="#{testBean.list}" var="item" varStatus="myVarStatus">
İndex Sayısı : #{myVarStatus.index}
</ui:repeat>
import javax.faces.application.*;
public class DomainResouceHandler extends ResourceHandlerWrapper {
private ResourceHandler wrapped;
public DomainResouceHandler(ResourceHandler wrapped) {
this.wrapped = wrapped;
}
@Override
public Resource createResource(final String resourceName, final String libraryName) {
final Resource resource = super.createResource(resourceName, libraryName);
return new ResourceWrapper() {
@Override
public String getRequestPath() {
return "http://example.com/"+resource.getRequestPath();
}
@Override
public Resource getWrapped() {
return resource;
}
};
}
@Override
public ResourceHandler getWrapped() {
return wrapped;
}
}
DomainResouceHandler sınıfı ResourceHandlerWrapper'dan extend edilmiş ve createResource method'u override edilmiştir. <application> <resource-handler>com.done.rabbit.support.resource.DomainResouceHandler</resource-handler> </application>
package com.fibiler.test;
import javax.faces.application.*;
import javax.faces.context.*;
import javax.servlet.http.*;
public class CustomViewHandler extends ViewHandlerWrapper{
private ViewHandler wrappped;
public CustomViewHandler(ViewHandler wrappped) {
super();
this.wrappped = wrappped;
}
@Override
public ViewHandler getWrapped() {
return wrappped;
}
@Override
public String getActionURL(FacesContext context, String viewId) {
HttpServletRequest request=(HttpServletRequest)FacesContext.
getCurrentInstance().getExternalContext().getRequest();
String url=request.getRequestURL().toString();
if(url==null){
return super.getActionURL(context, viewId);
}
return "http://www.example.com"+super.getActionURL(context, viewId);
}
}
Yukarıdaki kodda getActionURL method'u override edilmiş ve action URL'inin başına http://www.example.com eklenmiştir. <application> <view-handler>com.fibiler.test.CustomViewHandler</view-handler> </application>Bu işlemleri yaptıktan sonra /kayit/index.jsf sayfasına girip form elementinin action değerini kontrol ettiğinizde http://www.example.com//kayit/index.jsf değerini görmeniz gerekir.
<h:outputText value="#{testBean.date}" >
<f:convertDateTime pattern="dd.MM.yyyy HH:mm" timeZone="Turkey" locale="tr_TR"/>
</h:outputText>
testBean'deki date alanı, Türkiye saatine göre dd.MM.yyyy HH:mm şeklinde formatlı gözükür.
protected ResourceBundle getBundle() {
if (bundle == null) {
FacesContext context = FacesContext.getCurrentInstance();
bundle = context.getApplication().getResourceBundle(context, "msg");
}
return bundle;
}
protected String getMessage(String key, String defaultValue) {
String result = null;
try {
result = getBundle().getString(key);
} catch (MissingResourceException e) {
return defaultValue;
}
return result;
}
gertMessage metoduna key ile resources dosyasından desteklenen Local'e göre bir değer alınabilir.
protected String getMessage(String key, String defaultValue,
String... parameters) {
String result = null;
try {
result = getBundle().getString(key);
if(result!=null){
return MessageFormat.format(result, parameters);
}else{
return result;
}
} catch (MissingResourceException e) {
return defaultValue;
}
}
<input type="text" id="inputJson" value="" style="display:none"/>
<button type="button"
class="button" id="copy-button" data-clipboard-target="#inputJson">Copy To Clipboard</button>
<br/>
<h:outputText id="inputTextPretty" value="#{inventoryBean.pretty}"
style="white-space: pre-wrap;"></h:outputText>
<h:outputScript name="clipboard.min.js" library="js"></h:outputScript>
<script>
var clipboard = new ClipboardJS('.button', {
text: function() {
return JSON.stringify(#{testBean.json});
}
});
</script>
<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.0</version> </dependency> <dependency> <groupId>javax.faces</groupId> <artifactId>javax.faces-api</artifactId> <version>2.3</version> </dependency> <dependency> <groupId>org.glassfish</groupId> <artifactId>javax.faces</artifactId> <version>2.3.9</version> </dependency> <dependency> <groupId>javax.enterprise</groupId> <artifactId>cdi-api</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>org.jboss.weld.servlet</groupId> <artifactId>weld-servlet</artifactId> <version>2.4.8.Final</version> </dependency>Ardından CDI için WEB-INF için beans.xml eklenir :
<?xml version="1.0" encoding="UTF-8"?> <beans 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/beans_2_0.xsd" bean-discovery-mode="all" version="2.0"> </beans>Ardından Tomcat 9 için META-INF altında context.xml eklenir :
<Context>
<Resource name="BeanManager"
auth="Container"
type="javax.enterprise.inject.spi.BeanManager"
factory="org.jboss.weld.resources.ManagerObjectFactory"/>
</Context>
web.xml'e aşağıdaki eklenir :<listener> <listener-class>org.jboss.weld.environment.servlet.Listener</listener-class> </listener> <resource-env-ref> <resource-env-ref-name>BeanManager</resource-env-ref-name> <resource-env-ref-type>javax.enterprise.inject.spi.BeanManager</resource-env-ref-type> </resource-env-ref>web.xml'in son hali şu şekilde olmalı :
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
<display-name>JSF2_3Test</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.xhtml</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<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>*.xhtml</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
</listener>
<resource-env-ref>
<resource-env-ref-name>BeanManager</resource-env-ref-name>
<resource-env-ref-type>javax.enterprise.inject.spi.BeanManager</resource-env-ref-type>
</resource-env-ref>
</web-app>
Artık ortam hazır demektir. En basit olarak aşağıdaki gibi bir index.xhtml sayfası yapalım :
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<head>
<meta charset="ISO-8859-9"/>
<title>Merhaba JSF 2.3</title>
</head>
<body>
<h:outputText value="Merhaba JSF 2.3"></h:outputText>
</body>
</html>
Artık bu projeyi Tomcat 9'da çalıştırabiliriz. Bu projeyi çalıştırdığınızda aşağıdaki gibi hatalar alabilirsiniz :Caused by: javax.faces.FacesException: Unable to find CDI BeanManager at com.sun.faces.application.ApplicationImpl.isJsf23(ApplicationImpl.java:2714) at com.sun.faces.application.ApplicationImpl.addELResolver(ApplicationImpl.java:549) at javax.faces.application.ApplicationWrapper.addELResolver(ApplicationWrapper.java:611) at org.jboss.weld.environment.servlet.jsf.WeldApplication.Bu durumda aşağıdaki gibi bir bean eklemek gerekir :(WeldApplication.java:72) at org.jboss.weld.environment.servlet.jsf.WeldApplicationFactory.getApplication(WeldApplicationFactory.java:46) at com.sun.faces.application.InjectionApplicationFactory.getApplication(InjectionApplicationFactory.java:88) at com.sun.faces.config.InitFacesContext.getApplication(InitFacesContext.java:153) at com.sun.faces.lifecycle.ClientWindowFactoryImpl. (ClientWindowFactoryImpl.java:63) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at java.lang.Class.newInstance(Class.java:442) at javax.faces.FactoryFinderInstance.getImplGivenPreviousImpl(FactoryFinderInstance.java:391) at javax.faces.FactoryFinderInstance.getImplementationInstance(FactoryFinderInstance.java:255) at javax.faces.FactoryFinderInstance.getFactory(FactoryFinderInstance.java:529) at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:292) at com.sun.faces.config.processor.FactoryConfigProcessor.verifyFactoriesExist(FactoryConfigProcessor.java:354) ... 33 more java.lang.IllegalStateException: Could not find backup for factory javax.faces.application.ApplicationFactory. at javax.faces.FactoryFinderInstance.getFactory(FactoryFinderInstance.java:541) at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:292) at com.sun.faces.config.InitFacesContext.getApplication(InitFacesContext.java:152) at com.sun.faces.config.ConfigureListener.contextDestroyed(ConfigureListener.java:367) at org.apache.catalina.core.StandardContext.listenerStop(StandardContext.java:4722) at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5395) at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:257) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:187) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1384) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1374) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134) at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:909) at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:841) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1384) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1374) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134) at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:909) at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) at org.apache.catalina.core.StandardService.startInternal(StandardService.java:421) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:930) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) at org.apache.catalina.startup.Catalina.start(Catalina.java:738) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:342) at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:473)
package com.fibiler.jsf2_3.hello;
import javax.faces.annotation.FacesConfig;
import javax.faces.annotation.FacesConfig.Version;
@FacesConfig(version = Version.JSF_2_3)
public class ConfigurationBean {
}
Bunu eklendikten sonra tomcat 9'u çalıştırırsanız hata gelmeyecektir. Hatanız sebebi projenizde bir bean olmamasıdır. Yukarıdaki ConfigurationBean'i eklemek yerine aşağıdaki gibi bir bean yapıp onu kullanalım:
import javax.inject.Named;
@Named
public class HelloBean {
private String message="Merhaba JSF 2.3";
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
Sayfa şu şekilde olacak :
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<head>
<meta charset="ISO-8859-9"/>
<title>Merhaba JSF 2.3</title>
</head>
<body>
<h:outputText value="#{helloBean.message}"></h:outputText>
</body>
</html>
Artık proje hata vermeyecektir. <dependency> <groupId>jakarta.faces</groupId> <artifactId>jakarta.faces-api</artifactId> <version>3.0.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.glassfish</groupId> <artifactId>jakarta.faces</artifactId> <version>3.0.1</version> </dependency> <dependency> <groupId>jakarta.servlet</groupId> <artifactId>jakarta.servlet-api</artifactId> <version>5.0.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>jakarta.servlet.jsp</groupId> <artifactId>jakarta.servlet.jsp-api</artifactId> <version>3.0.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>jakarta.el</groupId> <artifactId>jakarta.el-api</artifactId> <version>4.0.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.jboss.weld.servlet</groupId> <artifactId>weld-servlet-shaded</artifactId> <version>4.0.0.Final</version> </dependency>Tomcat 9, Jakarta EE 9'u desteklemektedir. Bu nedenle Jakarta kullanılmaktadır. Weld kütüphanesi CDI için eklenmektedir. CDI için META-INF klasörü altında context.xml eklenir:
<Context>
<Resource name="BeanManager"
auth="Container"
type="jakarta.enterprise.inject.spi.BeanManager"
factory="org.jboss.weld.resources.ManagerObjectFactory" />
</Context>
Ardından WEB-INF altına boş bir beans.xml dosyası konulur:
<beans 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/beans_3_0.xsd"
bean-discovery-mode="all">
</beans>
Web.xml aşağıdaki gibi olsun :<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0"> <display-name>web</display-name> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>jakarta.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> </web-app>faces-config.xml ise aşağıdaki gibidir :
<?xml version="1.0" encoding="UTF-8"?>
<faces-config
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_3_0.xsd"
version="3.0">
</faces-config>
Artık bir Bean yaratabiliriz :
package com.test;
import jakarta.inject.Named;
@Named
public class HelloBean {
private String message="Merhaba JSF 3.0";
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
Bu bean'i kullanan bir sayfa yapalım :
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>Hello JSF 3.0</title>
</h:head>
<h:body>
<h1>#{helloBean.message}</h1>
</h:body>
</html>