# WebSocket in Eclipse Web Projekt implementieren



## Kenan89 (1. Jun 2012)

Hallo Leute,

seit 2 Tagen informiere ich mich bereits über WebSockets und habe schon viel darüber in Erfahrung gebracht.

Ich fand auch Tutorials, die aber bei mir nicht klappten. Da ich in meiner Umgebung niemanden kenne, der mir diesbezüglich weiterhelfen kann, hoffe ich, dass sich hier jemand findet, der bereits WebSockets erfolgreich verwendet hat.

Es gibt ja WebSocket Server (Jetty, JWebSocket, Netty,...). Ich möchte meine webapps aber weiterhin bei tomcat deployen, deswegen brauche ich die Schnittstelle zu den WebSocket Servern.

Nun las ich, dass tomcat 7.027 WebSockets unterstützt, also habe ich wieder ein Tutorial durchgearbeitet, was mich aber nicht auf die Lösung brachte. Ich denke aber, ich bin sehr nah dran.

Schau mal mein Code:
web.xml

```
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                      http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
  version="3.0"
  metadata-complete="true">

    <description>
     Testttttttttttttt
    </description>
    <display-name>Teeeeestttt</display-name>


    <servlet>
		<servlet-name>wsChat</servlet-name>
	<servlet-class>
		com.ChatWebSocketServlet
	</servlet-class>
	</servlet> 
	<servlet-mapping>
		<servlet-name>wsChat</servlet-name>
	<url-pattern>/com/ChatWebSocketServlet</url-pattern>
	</servlet-mapping>

</web-app>
```


```
package com;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;

import org.apache.catalina.websocket.MessageInbound;
import org.apache.catalina.websocket.StreamInbound;
import org.apache.catalina.websocket.WebSocketServlet;
import org.apache.catalina.websocket.WsOutbound;

public class ChatWebSocketServlet extends  WebSocketServlet{

	@Override
	protected StreamInbound createWebSocketInbound(String subProtocol) {
		return new ChatMessageInbound();
	}


	
	private final class ChatMessageInbound extends MessageInbound {
		
		@Override
		protected void onOpen(WsOutbound outbound){
			System.out.println("onOpen");
		};
		 
		
		protected void onClose(int status){
			System.out.println("onClose");
		}
		
		@Override
		protected void onBinaryMessage(ByteBuffer message)
		throws IOException {
		//this application does not expect binary data
		throw new UnsupportedOperationException(
		"Binary message not supported.");
		}
		 
		@Override
		protected void onTextMessage(CharBuffer message) throws IOException {
		String msg = message.toString();
		//modify the message by adding a timestamp
		//msg = “(“ + System.currentTimeMillis()+”) “+ msg;
		broadcast(msg);
		}
		 
		private void broadcast(String message) {
		//write some code to process the message
		}
	}
}
```


```
<!DOCTYPE html>

<html>

<head>
	<title>Websocket</title>
	<script type="text/javascript" src="jquery-1.7.2.min.js"></script>
</head>
	
<body>

	<form action="#" id="chat_form" method = "post">
		<input id="msg">
		<input type="submit" value="senden">
	</form>

	<script>
		
		var websocket = new WebSocket('ws://localhost:8080/wsChat');
	
		websocket.onopen = function(event){
			$('#chat').append('<br> Connection...');
		}
		
		websocket.onmessage = function(event){
			$('#chat').append(event.data);
		}
		
		websocket.onclose = function(event){
			$('#chat').append("<br> closed");
		}
		
		$(function(){
			$('form#chat_form').submit(function(e){
				e.preventDefault();
				var textfield = $('#msg');
				websocket.send(textfield.val());
				textfield.val("");
			})
		});
		
	</script>
	
</body>

</html>
```

Fehlermeldung in FireFox-Konsole:


> Firefox kann keine Verbindung zu dem Server unter ws://localhost:8080/wsChat aufbauen.



Die Klasse ist doch in der web.xml registriert?!

Danke im voraus.


----------



## maki (1. Jun 2012)

Hi,



> Die Klasse ist doch in der web.xml registriert?!


Ja, aber unter /com/ChatWebSocketServlet.

Läuft denn der Tomcat?
Was ist der HTTP Statuscode? (404, 500, etc. pp.)


----------



## Kenan89 (1. Jun 2012)

Der HTTP Fehler Code ist 404...
Der Servlet Name ist doch egal. Wichtig ist doch die Servlet url(url pattern)?
Momentan kann ich es leider nicht ausprobieren mit deinem Vorschlag. 
Morgen sitze ich wieder an diesem Thema, irgendwann sollte es dann
klappen. Bin ja nicht der einizige der WebSockets implementiert.


----------



## Kenan89 (4. Jun 2012)

Hmm.. immer noch der gleiche Fehler. FireFox sagt, er kann das Servlet nicht finden. Laut einem weiteren Tutorial habe ich folgendes programmiertähnlich wie der oben)

Java-Klasse

```
package com;

public class TestServlet extends WebSocketServlet{

	@Override
	protected StreamInbound createWebSocketInbound(String arg0) {
		return null;
	}
	
    class TheWebSocket extends MessageInbound
    {
    	private WsOutbound outbound;
    	
        @Override
        public void onOpen( WsOutbound outbound ){
            // This method is called when a WebSocket has a connection
        	this.outbound = outbound;
        }

        public void onTextMessage( CharBuffer buffer ) throws IOException{
            // This method is called when a WebSocket receives a message
        	 outbound.writeTextMessage( buffer );
        }

		protected void onBinaryMessage(ByteBuffer arg0) throws IOException {}
    }

}
```

Web.xml

```
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  
    <display-name>WebSocket Web Application</display-name>
  
    <servlet>
        <servlet-name>TestServlet</servlet-name>
        <servlet-class>com.TestServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>TestServlet</servlet-name>
        <url-pattern>/com/TestServlet</url-pattern>
    </servlet-mapping>

    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

</web-app>
```

index.jsp

```
<!DOCTYPE html>

<html>

<head>
	<title>Websocket</title>
	<script type="text/javascript" src="jquery-1.7.2.min.js"></script>
</head>
	
<body>

	<form action="#" id="chat_form" method = "post">
	
		<input id="msg">
		
		<input type="submit" value="senden">
	
	</form>

	<script>
		
		var websocket = new WebSocket('ws://localhost:8080/com/TestServlet');
	
		websocket.onopen = function(event){
			$('#chat').append('<br> Connection...');
		}
		
		websocket.onmessage = function(event){
			$('#chat').append(event.data);
		}
		
		websocket.onclose = function(event){
			$('#chat').append("<br> closed");
		}
		
		$(function(){
			$('form#chat_form').submit(function(e){
				e.preventDefault();
				var textfield = $('#msg');
				websocket.send(textfield.val());
				textfield.val("");
			})
		});
		
	</script>
	
</body>

</html>
```

Er findet das Servlet nicht, also stimmt was mit der web.xml nicht, oder?

Die Ordner Struktur ist so aufgebaut(ich verwendet Eclipse mit TomCat 7.0.27)








[EDIT]
Ich habe jetzt Testweise eine Klasse programmiert und die in meiner index.jsp instanziert. In der Klasse lasse ich im Konstruktor nur etwas mit System.out.println("...") ausgeben. Es funktioniert, und ich kriege die Ausgabe in die Konsole.

Aber weiterhin gibt es mit der web.xml das Problem, dass er meine Java Klasse nicht findet. Also müsste entweder da etwas falsch sein, oder in meiner JavaScript-Zeile: 

```
var websocket = new WebSocket('ws://localhost:8080/TestServlet');
```
[/EDIT]


----------



## maki (4. Jun 2012)

> Der HTTP Fehler Code ist 404...


Sicher dass die URL stimmt?



> Der Servlet Name ist doch egal. Wichtig ist doch die Servlet url(url pattern)?


Eben, und die war falsch, siehe meinen letzten Post.


Bei deinem neuesten Beispiel, mit welcher URL versuchst du es?
Was ist der HTTP Status Code?


----------



## Kenan89 (4. Jun 2012)

> Bei deinem neuesten Beispiel, mit welcher URL versuchst du es?
> Was ist der HTTP Status Code?



Der Fehlercode ist weiterhin 404.
Ich habe jetzt Testweise eine Klasse programmiert und die in meiner index.jsp instanziert. In der Klasse lasse ich im Konstruktor nur etwas mit System.out.println("...") ausgeben. Es funktioniert, und ich kriege die Ausgabe in die Konsole.

Aber weiterhin gibt es mit der web.xml das Problem, dass er meine Java Klasse nicht findet. Also müsste entweder da etwas falsch sein, oder in meiner JavaScript-Zeile:
Java Code: Quelltext in neuem Fenster öffnen


```
var websocket = new WebSocket('ws://localhost:8080/TestServlet');
```

Gerade mit web.xml hatte ich bisher nur sehr wenig zu tun, deswegen kann ich leider nicht genau sagen, ob etwas fehlt, oder ob die URL falsch ist. Deswegen habe ich ein Screenshot von der Ordnerstruktur meines Projektes gemacht und hochgeladen.


----------



## maki (4. Jun 2012)

Schau di9r mal das URL Mapping genau an:
[xml]    <servlet-mapping>
        <servlet-name>TestServlet</servlet-name>
        <url-pattern>/com/TestServlet</url-pattern>
    </servlet-mapping>[/xml]
Da steht, dass dir URL [c]/com/TestServlet[/c] zu deinem Serlvet führt, [c]/TestServlet[/c] ist nicht richtig.

Die richgtige URL  sollte lauten:
[c]protokoll://loalhost:8080/<context>/com/TestServlet[/c]
Versuchs mal aus einem browser folgende URL:
[c]http://loalhost:8080/<context>/com/TestServlet[/c]
sollte zumindest einen 500 Fehler geben.

<context> ist der SerlvetContext, ist in der IDE meist leer oder der Name des WebApp Projektes.


----------



## Kenan89 (4. Jun 2012)

maki hat gesagt.:


> Schau di9r mal das URL Mapping genau an:
> [xml]    <servlet-mapping>
> <servlet-name>TestServlet</servlet-name>
> <url-pattern>/com/TestServlet</url-pattern>
> ...



Klappt leider nicht ;(
Meine neue URL im Mapping: 


> <servlet-mapping>
> <servlet-name>TestServlet</servlet-name>
> <url-pattern>localhost:8080/WS2/com/TestServlet</url-pattern>
> </servlet-mapping>



Ausserdem habe ich im Browser eingegeben: localhost:8080/WS2/com/TestServlet

Leider immer noch Error 404.

JavaScript-Zeile immer noch gleich: 
	
	
	
	





```
var websocket = new WebSocket('ws://localhost:8080/TestServlet');
```


----------



## maki (4. Jun 2012)

> }Meine neue URL im Mapping


Wieso machst du das?
Hat doch keiner gesagt dass du ein kaputtes Mapping in die web.xml einträgst??? :noe:

Stell das wieder richtig und probier es dann nochmal, einmal mit und einmal ohne Context.


----------



## Kenan89 (4. Jun 2012)

Schon klar, ich habe bereits, bevor ich gepostet habe alle möglichen Varianten ausprobiert. Hätte ich noch erwähnen sollen.


----------



## maki (4. Jun 2012)

"Alle möglichen Varianten probieren" ohne Plan ist nur trial & error.

Welchen Statuscode bekommst du?

Wie sieht denn nun deine web.xml aus?


----------



## Kenan89 (4. Jun 2012)

Ja, leider bin ich momentan wirklich auf trial and error.

Statuscode immer noch 404.

web.xml

```
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  
    <display-name>WebSocket Web Application</display-name>
  
    <servlet>
        <servlet-name>TestServlet</servlet-name>
        <servlet-class>com.TestServlet</servlet-class>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>TestServlet</servlet-name>
        <url-pattern>localhost:8080/WS2/com/TestServlet</url-pattern>
    </servlet-mapping>

    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

</web-app>
```


----------



## Kenan89 (4. Jun 2012)

Sry, für den Doppelpost, aber oben kann ich keine Datei mehr einfügen.
Hier das Projekt, wenn es jemand testen will. Es muss Tomcat 7.0.27 Server
verwendet werden.

Ausserdem müsst ihr im Ordner lib des tomcat-Verzeichnisses die jars importieren(Build path)


----------



## maki (4. Jun 2012)

???

Sorry Kenan, aber wie soll ich dir helfen wenn du anscheinend nur wild Knöpfe drückst... 
Lies doch bis nochaml was ich bisher geschrieben habe, dein aktuelles URL Mapping ist immer noch falsch, mach das wieder richtig.


----------



## Kenan89 (4. Jun 2012)

maki hat gesagt.:


> ???
> 
> Sorry Kenan, aber wie soll ich dir helfen wenn du anscheinend nur wild Knöpfe drückst...
> Lies doch bis nochaml was ich bisher geschrieben habe, dein aktuelles URL Mapping ist immer noch falsch, mach das wieder richtig.



Hä, ich habe es doch so gemacht, wie du es oben beschrieben hast:



> Die richgtige URL sollte lauten:
> *protokoll://loalhost:8080/<context>/com/TestServlet*
> Versuchs mal aus einem browser folgende URL:
> http://loalhost:8080/<context>/com/TestServlet
> sollte zumindest einen 500 Fehler geben.





> <servlet-mapping>
> <servlet-name>TestServlet</servlet-name>
> <url-pattern>*localhost:8080/WS2/com/TestServlet*</url-pattern>
> </servlet-mapping>



Das WS2 ist der Context. Wenn du kritisierst, dass "protokoll://" davor fehlt, damit habe ich es schon ausprobiert und funktionierte auch nicht(Error 404), also so:  <url-pattern>protokoll://localhost:8080/WS2/com/TestServlet</url-pattern>.

Oder habe ich dich falsch verstanden?


----------



## maki (4. Jun 2012)

Ich meinte URL, nicht URL PAttern, lass mal das alte Pattern drinnen:
[xml]    <servlet-mapping>
        <servlet-name>TestServlet</servlet-name>
        <url-pattern>/com/TestServlet</url-pattern>
    </servlet-mapping>[/xml]
Die URLs die ich gepostet hatte solltest du mit einem Browser testen.


----------



## Kenan89 (4. Jun 2012)

Nicht gefunden Error 404 ;(

also Pattern sind so, wie du gepostet hast.

In die Linkleiste habe ich auch beide Varianten eingetippt.
localhost:8080/WS2/com/TestServlet
und
protokoll://localhost:8080/WS2/com/TestServlet
 Leider 404.
Er findet das blöde Servlet nicht.;(


----------



## maki (4. Jun 2012)

[c]http://localhost:8080/WS2/com/TestServlet[/c]
und
[c]http://localhost:8080/com/TestServlet[/c]
auch?


----------



## Kenan89 (4. Jun 2012)

Ja, leider.
Aber schau mal: Ich habe ein komplett neues Projekt in Eclipse angelegt.
Dann habe ich ein package "com" in src Ordner erstellt und darin ein neues Servlet angelegt, welches vom WebSocketServlet erbt. Die Klasse:


```
package com;

@WebServlet("/WS")
public class WS extends WebSocketServlet {

    public WS() {
        super();
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		PrintWriter w = response.getWriter();
		w.println("TEST");
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
	}

	@Override
	protected StreamInbound createWebSocketInbound(String arg0) {
		return null;
	}
}
```

Diesen erreiche ich unter dem Link: http://localhost:8080/WS2/WS

Wenn ich mich dann aber mit der index.jsp connecten will kann keine Verbindungzum WebSocketServlet  aufgebaut werden. 

```
var websocket = new WebSocket('ws://localhost:8080/WS2/WS');
```

EDIT: Das gute ist allerdings, das er den Servlet findet, denn der Error 404 kommt nur wenn ich die url in javascript ändere. Momentan kommt kein Fehler, sondern er sagt nur, er kann sich nicht mit dem Server verbinden.


----------



## Kenan89 (4. Jun 2012)

Uff, nach Einarbeiten in den chat-Example im tomcat 7 Ordner ist gelungen


----------

