01100011 Evelyn am 21 May 2011 - 08:54

Es müsste eine Erweiterung von Filezilla geben, die sich ins Kontextmenü integriert, und wenn man auf “Senden an” geht, dann -> “Filezilla” kommt und ein weiteres Menü, wo man direkt auf das Benutzerkonto klicken kann.
Natürlich müsste dann dynamisch weiteres Menüs geladen werden. Nämlich die Ordnerstruktur.

Gibt es sowas schon?
Vll. sollte ich das mal an Filezilla unter “wanna have” schreiben ^^

01100011 Evelyn am 04 May 2011 - 10:17

Entwickeln in bestehenden Systemen ist etwas, dass einem Programmierer die Arbeit schwer machen kann, definitiv aber etwas für neugierige Geister ist.

Zumindest für jene, die früher schon gerne die Mickey Maus gelesen haben und das Detektivspielzeug toll fanden ^^

In einem System mit Hunderten von Eventhandlern und null Dokumentation, wird das Suchen nach einem Fehler zur richtigen Detektivarbeit.

In dem Fall lob ich mir Haltepunkte. So kann man unwichtige Punkte überspringen und sich so langsam vorarbeiten.

Aus der Reihe:
Code schreiben ist … Puzzeln
Code schreiben ist … Abenteuer

01100011 Evelyn am 02 May 2011 - 13:37

Einer meiner Lieblingssprüche beim Entwickeln, der mir leider viel zu oft wieder in den Kopf kommt.
Aus gegebenem Anlass, versteht sich:

Diskontinuität ist Projektfeind Nummer 1
Rainer Kollmeier, Frühjahr 2010

01100011 und Webzeug Evelyn am 12 Apr 2011 - 12:19

Wann immer ich mal wieder was getestet und verhauen habe, wünsche ich mir eine Versionsverwaltung her. Letztens überlegte ich, doch einfach einen lokalen SVN auf den Rechner zu packen, aber als Netzmensch kommen dann so Überlegungen wie “aber wenn ich mal von woanders drauf zugreifen will?” ins Spiel.

Einen Onlineanbieter zu finden, wo man sich nicht komplett nackig machen muss (d.h. der Code für alle Welt zugänglich ist) ist nicht leicht zu finden. Letztlich wurde ich bei bitbucket aber fündig:

Bitbucket bietet dir unlimited diskspace; unlimited repositorys, die auch private sind bzw. sein können und man kann noch bis zu 5 weitere User in das Repositoy mit einladen. Und das für: free. Awesome.

Ich habs jetzt mal getestet. Es ist super.
Der “Haken” an der Sache ist, dass man nicht direkt mit SVN Tortoise arbeiten kann, wie man es kennt, sondern sich TortoiseHg herunterladen und installieren muss. Die Bedienung damit ist auch etwas umständlicher, aber who cares? Es funktioniert. Eine ungefähre Anleitung bietet bitbucket auch.

Dennoch im Folgenden eine Anleitung von mir. Vll. habt ihr es ja auch schon mal probiert und kennt einen einfacheren Weg? (Ich steh im allgemeinen etwas auf Kreigsfuß mit solchen Versionsverwaltungen, fragt nicht wieso, kA)

Erstellen eines neuen Repositorys online

Verbinden des Online-Repositorys mit dem lokalen Projekt

Derzeit weiß ich es nur so, dass ein neuer Ordner angelegt werden muss. Wie der heißt, ist egal, aber er muss leer sein.
Dann Rechts-Klick auf den Ordner und den Hg-Workbench aufwählen:

Darin auf File -> Clone Repository

und im folgenden Menüfenster als Source den Pfad zum Online-Repository angeben

Fertig. Anschließend die Dateien, die zu dem Projekt gehören, in den Ordner reinkopieren.

Änderungen Committen

Wenn man einchecken will und wie man es ja kennt auf “Commit” geht, passiert gar nichts. Man erhält zwar grüne Haken vor den Dateien, aber hochgeladen ist nichts. Dafür muss man synchronisieren und dann “pushen”.
Im Workbench selektiert man also sein Projekt und klickt auf den Button mit den beiden grünen Pfeilen:

Anschließend selektiert man alle Dateien, die sich geändert haben bzw. synchronisiert werden sollen, schreibt einen Kommentartext und klickt auf den unscheinbaren Button “Übernehmen”

Die Meldung “Add untracked Files?” mit Klick auf “Add” bestätigen.
Nun aktualisiert sich der obere Bereich im Workbench und man sieht einen neuen Eintrag, der in der Beschreibung den eben eingegebenen Kommentar trägt.

Das wars aber noch nicht. Man sieht, dass die Dateien jetzt ein blaues Plus tragen, muss sie letztendlich aber noch hochladen, also pushen:

Als Erfolgsmeldung sieht man unten links, wie eine prozentuale Anzeige nach oben zählt und anschließend mit “Push completed” endet. Diese Anzeige bleibt aber nur kurz dort stehen.

Ich finde das alles nicht wahnsinnig intuitiv, aber man kann damit umgehen und wenn man online schaut, sind auch alle Dateien vorhanden:

Immerhin das, worauf es ankommt :)

Sobald ich einen besseren resp. einfacheren Weg erschlossen habe, werde ich darüber berichten.

01100011 Evelyn am 25 Mar 2011 - 12:37

September 2008. So lange ist es her, dass ich über das Programm schrieb, und so lange hab ich es glaube auch nicht mehr benutzt. Nach einem Serverumzug geht es mir aber tierisch auf den Kranz, dass ich für kleine Änderungen an der Datenbank, oder einfach um was nachzugucken, immer durch das ganze Menü von Plesk klickern muss, um dann nach paar Minuten alles von vorne zu beginnen, da nach Untätigkeit natürlich ein Timout kommt.

Schön ist, dass das Programm EMS SQL Manager for MySQL noch immer in einer Freeware-Version zu haben ist, mit der man jedoch nur fünf Datenbanken gleichzeitig verwalten kann und jede von ihnen 100MB nicht überschreiten darf. Für den allgemeinen Gebrauch reicht dies aber völlig.

Das Programm an sich ist recht einfach zu handeln. Der Zugriff vom Desktop aus geschieht via HTTP-Tunneling. Dafür lädt man die Datei emsproxy.php (die ich sicherheitshalber umbenannt habe) in ein Verzeichnis des Webspace und “registriert” im Programm eine neue Datenbank.


Der Screenshot zeigt, wie eine Datenbank angelegt werden kann. Nach Klick auf “Next” kann man dann den Pfad zur emsproxy.php auf dem Server angeben.

Und schon kann man ganz viele tolle Sachen machen *juhu*

01100011 Evelyn am 20 Mar 2011 - 21:24

Weil mich der Fehler schon wieder ewig aufgehalten hat, will ich einfach mal die Lösung festhalten.

Ich arbeite mit einem Amazon Webservice, um meine Bücher leichter in die Datenbank pflegen zu können. In der Benutzung bekam ich allerdings beim Seitenwechsel diesen Fehler:

Warning: session_start() [function.session-start]: Node no longer exists in $pfad on line $ziffer

Warning: Unknown: Node no longer exists in Unknown on line 0

Die Lösung fand sich im PHP-Resource-Forum:

I was using SimpleXMLElement and even though the value in the XML value could be printed to the screen with no error, reading that value into a session variable caused the error.

Resolution…

stick (string) before the XML object. E.g:
PHP Code:

$MyValue= (string)$data->viewentry->entrydata[0]->text;

-_-” Darauf wär ich nie gekommen.

01100011 Evelyn am 19 Mar 2011 - 11:32

Cool, man kann den Windows Explorer jetzt auch zum Tabbed Browsing bringen.
Das Programm QTTabbar gab es schon länger, allerdings funktionierte das für Vista nur manchmal, für Windows7 gar nicht. Mit der momentanen Version 1.5 ist es jetzt aber möglich :)

QTTabbar 1.5 (Beta)

Sowas hab ich mir schon lange gewünscht (sieht jetzt nicht sooooo schick aus, ist aber funktioniert)

(via)

Ps.: Den Nautilus wünsche ich mir aber trotzdem noch für Windows
PPs.: So Toolbars sind ja richtig praktisch, bei den immer niedriger werdenden Bildschirmen ist es aber nur ätzend. Wo sind die 4:3-Bildschirme für BUSINESS-Notebooks?

01100011 Evelyn am 05 Mar 2011 - 11:00

Will man mehrere Webserver lokal betreiben, können die sich aufgrund ihrer Standardports schon mal in die Quere kommen. Ich habe derzeit z.B. den IIS und einen Apache laufen, die sich allerdings behakeln. Der Tomcat hat sich bei Port 8080 ja ziemlich unauffällig dazuinstalliert.

Um den Port im Apache zu ändern, ändert man einfach unter

~\xampp\apache\conf\httpd.conf\
die Zeile Listen 80
in Listen 81

01100011 Latita am 27 Feb 2011 - 09:20

Dies wird das zweite vollständige Beispiel werden, dass ich euch vorstellen möchte. Vollständig heißt, dass es ein “standalone”-Tutorial ist, das sich auf kein vorhergehendes Beispiel bezieht. Das habe ich für das nächste Mal geplant. Wie bei Tutorials üblich, wird es auch wieder das gesamte Beispiel zum Download geben.

Heute werden wir uns also ein kleines, ganz einfaches, Login-Form bauen. Damit ist es aber nicht getan, wir werden die Eingaben validieren und die Internationalisierung einführen.

Wir brauchen

Für die Installation des Tomcat-Servers bitte ich dann aber doch in diesen Artikel zu schauen: Struts 1 – Hello World

Für die Installation des Plugins könnt ihr hier nachschauen (an sich keine große Sache, aber die auf der verlinkten Seite werden noch zwei Vereinfachungen bei der Arbeit mit properties beschrieben, die für mich jedoch nicht notwendig waren). Der Link führt deshalb auf eine Google-Cache-Seite, da die EPFE-Seite zur Zeit der Artikelerstellung schon ne Weile einen MySQL-Fehler meldete.

Die Umsetzung

Folgendes Bild zeigt die Ordnerstruktur und passenderweise auch alle Librarys, die für diese Anwendung benötigt werden. Ich hab mir angewöhnt, immer nur die wirklich notwendigen Librarys einzubinden. Das bedingt zwar manchmal langwieriges Exceptionhopping, aber letztendlich versteht man besser, was wo liegt und was man braucht.

Kommen wir zu den Inhalten der Dateien:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>StrutsSimpleLogin</display-name>
  
  <servlet>
    <servlet-name>action</servlet-name>
    
    <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
    
    <init-param>
      <param-name>config</param-name>
      <param-value>/WEB-INF/struts-config.xml</param-value>
    </init-param>
    
    <load-on-startup>2</load-on-startup>
  </servlet>
  
  <servlet-mapping>
    <servlet-name>action</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>
  
  <welcome-file-list>
    <welcome-file>/login.jsp</welcome-file>
  </welcome-file-list>
  
</web-app>
<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE struts-config PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
          "http://struts.apache.org/dtds/struts-config_1_3.dtd">
          
<struts-config>
	<form-beans>
		<form-bean name="LoginForm" type="forms.LoginForm" />
	</form-beans>      
	
	<action-mappings>
		<action input="/login.jsp" 
				name="LoginForm" 
				path="/Login" 
				scope="request" 
				validate="true"
				type="actions.LoginAction">
			<forward name="success" path="/success.jsp" />
			<forward name="failure" path="/failure.jsp" />
		</action>
	</action-mappings>
	
	<message-resources parameter="ApplicationResource" />    
	
	<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
		<set-property property="pathnames"
					value="/org/apache/struts/validator/validator-rules.xml,
							/WEB-INF/validation.xml" />
	</plug-in>
	
</struts-config>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
<%@taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>    
 
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title><bean:message key="login.title" /></title>
</head>
<body>
	<div style="color:red">
		<html:errors />
	</div>
	
	<html:form action="/Login" >
		<bean:message key="login.label.username" /> <html:text name="LoginForm" property="username" />
		<bean:message key="login.label.password" /> <html:password name="LoginForm" property="password"></html:password>
		<html:submit><bean:message key="login.submit" /></html:submit>
	</html:form>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title><bean:message key="login.success.title" /></title>
</head>
<body>
	<bean:message key="login.success.message" /> <bean:write name="LoginForm" property="username" />
</body>
</html>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title><bean:message key="login.failure.title" /></title>
</head>
<body>
	<bean:message key="login.failure.message" />
</body>
</html>
package forms;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;

public class LoginForm extends ActionForm {
	
	private static final long serialVersionUID = 1L;
	private String username;
	private String password;
	
	public void setUsername(String username)
	{
		this.username = username;
	}
	
	public void setPassword(String password)
	{
		this.password = password;
	}
	
	public String getPassword()
	{
		return this.password;
	}
	
	public String getUsername()
	{
		return this.username;
	}
	
	public ActionErrors validate(ActionMapping mapping,
								HttpServletRequest request)
	{
		ActionErrors errors = new ActionErrors();
		if(username == null || username.length() < 1)
		{
			errors.add(username, new ActionMessage("error.username.required"));
		}
		if(password == null || password.length() < 1)
		{
			errors.add(password, new ActionMessage("error.password.required"));
		}
		return errors;
	}
}
package actions;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import forms.LoginForm;

public class LoginAction extends Action {
	
    public ActionForward execute(ActionMapping mapping, 
			ActionForm form,
			HttpServletRequest request, 
			HttpServletResponse response)
	throws Exception 
	{
	
		LoginForm loginForm = (LoginForm) form;
		
		if (loginForm.getUsername().equals(loginForm.getPassword())) 
		{
			return mapping.findForward("success");
		} 
		else 
		{
			return mapping.findForward("failure");
		}
	}
}

login.title = Login-Form
login.submit = Login
login.label.username = Username 
login.label.password = Password
login.failure.message = Sry, login failed.
login.failure.title = Failure
login.success.message = Hello, nice to see you again, 
login.success.title = Success

error.username.required = User Name is required.
error.password.required = Password is required.

# -- standard errors --
errors.header=<UL>
errors.prefix=<LI>
errors.suffix=</LI>
errors.footer=</UL>
# -- validator --
errors.invalid={0} is invalid.
errors.maxlength={0} can not be greater than {1} characters.
errors.minlength={0} can not be less than {1} characters.
errors.range={0} is not in the range {1} through {2}.
errors.required={0} is required.
errors.byte={0} must be an byte.
errors.date={0} is not a date.
errors.double={0} must be an double.
errors.float={0} must be an float.
errors.integer={0} must be an integer.
errors.long={0} must be an long.
errors.short={0} must be an short.
errors.creditcard={0} is not a valid credit card number.
errors.email={0} is an invalid e-mail address.
# -- other --
errors.cancel=Operation cancelled.
errors.detail={0}
errors.general=The process did not complete. Details should follow.
errors.token=Request could not be completed. Operation is not in sequence.
login.title = Anmeldung
login.submit = Anmelden
login.label.username = Benutzername 
login.label.password = Passwort
login.failure.message = Oh, Anmeldung fehlgeschlagen.
login.failure.title = Fehler
login.success.message = Hallo, schön dich zu sehen, 
login.success.title = Erfolg

error.username.required = Es muss ein Benutzername angegeben werden.
error.password.required = Es muss ein Passwort angegeben werden.

validation.xml

Diese Datei habe ich hier nicht aufgeführt, obwohl sie in der struts-config angegeben ist und auch auf dem Screenshot zu sehen ist. Im Download wird sie auch dabei sein. Prinzipiell gibt es zwei Wege seine Eingaben zu validieren. Einmal den Weg über das LoginForm, den ich in diesem Fall gewählt habe, als auch über die validation.xml, was vermutlich sogar die bessere Praxis wäre, im Sinne von gutem Code. Lesenswert dazu ist vll. der Artikel der tech-allies (hab mich nicht weiter damit befasst)

ApplicationResource.properties

Was mich bei vielen Frameworks stört ist das scheinbare Gezauber an manchen Stellen. Die ApplicationResource.properties gehört dazu. Ich habe meiner deutschen Version den Suffix “de_DE” angehangen und bei der Ausführung war sofort klar, dass die Buttons nun deutsche Label kriegen würden; ohne dass ich noch irgendwo etwas angegeben hätte. Nun ja; hinnehmen, freuen.

Cool ist jedenfalls, dass wir durch die Verwendung der properties und die Einbindung über bspw. <bean:message key="login.failure.message" /> unsere Inhalte total leicht wartbar gemacht haben. Wir können auf einen Schlag mehrere Sprachen auf einer Seite zur Verfügung stellen und haben bei Änderungen keinen großen Aufwand. Wir müssen die jsp.-Seiten nicht mal mehr anfassen.

Was passiert nun bei einem Aufruf der Seite?

Zum Ausführen der Applikation, klickt man im Projekt-Explorer mit Rechtsklick auf den Namen des Projektes -> Run As -> Run on Server

  • 1 und 2: Der User ruft die URL auf; da kein genauer Pfad angegeben wurde, schaut Tomcat in die web.xml und liefert die in der <welcome-file-list> definierte login.jsp als Startseite an den User zurück.
    In der login.jsp gibt es zwei Controls, deren Werte später in der LoginForm.java gespeichert werden sollen. Darum wird zu diesem Zeitpunkt die LoginForm schon instanziiert, zur Laufzeit jedoch nur ein Mal. Hierbei wird die “overridable” Funktion reset() aufgerufen. Dies ist der Konstruktor dieser Klasse und hier kann man beim initialisieren auch Defaultwerte mitgeben. Man sollte diese Funktion immer überschreiben und wichtige Eingabefelder auf null bzw “” setzen, da sonst bei mehreren Aufrufen Datenreste ungewünschte Effekte hervorrufen können.
  • 3: Der User füllt die Eingabefelder aus und schickt mit dem Drücken des submit-Buttons einen Request an den Server.
    In der login.jsp haben wir festgelegt, dass die action="/Login" ausgeführt werden soll. Beim Abschicken erhält diese die Endung *.do angehangen. Nun wird in der web.xml geschaut, was mit *do’s passieren soll und man wird über die Festlegungen im <servlet> an die struts.xml weitergereicht.
  • 4: Hier passiert ziemlich viel. In <action-mappings> steht, was passieren soll, wenn ein Request mit dem path = "/Login" hier ankommt.
    • a: zuerst einmal werden die Eingaben über die Setter in die LoginForm geschrieben
    • b: anschließend wird die validate()-Methode des LoginForms aufgerufen, da wir ja in der struts-config.xml validate="true" angegeben haben.
  • 5: Hier entscheidet sich: wurden die Daten korrekt in die Eingabefelder eingegeben (d.h. in dem Fall, sind die Felder nicht leer)?
    • Wenn nein, wird der User mit den errors an seinen Ursprung input="/login.jsp" zurückgeschickt und die Fehlermeldungen über das <html:errors /> angezeigt.
    • Sind die Eingaben valide, kommen wir in die actions.LoginAction.java und die execute()-Methode wird ausgeführt.
      Je nach Ergebnis der Prüfung der Eingaben, wird ein success oder failure zurückgeliefert
  • 6: Und je nachdem was wir in den forwards für solche Fälle definiert haben, wird dem User die Ergebnisseite präsentiert.

Downloads

BeispielProjekt als *.rar
Ausführbares *.war

Lesenswert

Beispiel A: Internationalisierung
Beispiel B: Internationalisierung
Types of Validation
Login Example with Struts 1

01100011 und Allgemein Latita am 26 Feb 2011 - 23:18

Ich hab mir gerade zwei kleine Plugins installiert, die mir bei der Veröffentlichung spezieller Inhalte helfen sollen.
Allerdings weiß ich nicht, ob die wirklich in WP3.1 funktionieren, darum dieser Beitrag. Ich bin gespannt.

Zum einen handelt es sich um das Plugin: RSS Post Editor
Alles, was zwischen den Tags [rss][/rss] steht, wird im Blog nicht angezeigt, dafür allerdings im Feed.
Test mit dem Satz “Drei Affen spielen mit Waffen”:
=>

Zum anderen handelt es sich um das Plugin RSSless
Dies funktioniert genau andesrum; Inhalte sind auf dem Blog sichtbar, im Feedreader allerdings nicht.
Der Testsatz zwischen den Tags [rssless][/rssless]:
=> Drei Affen spielen mit Waffen

Funktionierts?

Seiten:  zurück 1 2 3 4 5 6 7 8 9 10 weiter