Archiv der Kategorie: Java

Java techdocs

Mocking SessionContext

I have a EJB:

@Stateless
@Remote
public class ejbBean implements EjbBean {
	@PersistenceContext
	private EntityManager em;
	@Resource
	private SessionContext ctx;
 
	public String someMethod() {
		String name = ctx.getCallerPrincipal().getName();
		return name;
	}
}
public class EjbBeanTest {
	@Rule
	public final MockitoRule mockitoRule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
	@Mock
	private EntityManager em;
	@Mock
	private SessionContext ctx;
 
	@InjectMocks
	private EjbBean cut;
 
	@Before
	public void setUp() {
		Principal p = mock(Principal.class);
		when(ctx.getCallerPrincipal()).thenReturn(p);
		when(p.getName()).thenReturn("TestUser");
	}
 
	@Test
	public void test() {
		String result = cut.someMethod();
		assertEquals("TestUser", result);
	}

causes the following exception

org.mockito.exceptions.base.MockitoException: 
Mockito cannot mock this class: interface javax.ejb.SessionContext.

Mockito can only mock non-private & non-final classes.

I made lot of searches over the web. (google, stackOverflow, git, everywhere)
I found some suggestions like https://stackoverflow.com/questions/32695925/how-do-i-mock-a-sessioncontext-injected-via-resource-in-java-ee.
I tried everything.
But what ever I tried I got failing test with the Error message above.
WTF.
My friend give me the tip … Don`t use an mocking framework, make your own dummy.
OK lets try this. Fill the one method I need then instantiate this.

public class DummySessionContext implements SessionContext {
...
	@Override
	public Principal getCallerPrincipal() {
		// TODO Auto-generated method stub
		Principal principal = () -> "TESTUSER";
		return principal;
	}
...	
}

And this brings a new Error up.

java.lang.Error: Unresolved compilation problems: 
	The type javax.xml.rpc.handler.MessageContext cannot be resolved. It is indirectly referenced from required .class files
	MessageContext cannot be resolved to a type

It turns out that there was a missing dependency in pom.
Because we have scope = provide

<dependency>
	<groupId>org.jboss.spec.javax.ejb</groupId>
	<artifactId>jboss-ejb-api_3.2_spec</artifactId>
	<scope>provided</scope>
</dependency>

my mentor said

provided -> means provided by ejb container
provided dependencies will NOT be there for tests
I think you have to create dependency with test

I added the following to my pom

<!-- needed SessionContext mock-->
<dependency>
	<groupId>org.jboss.spec.javax.xml.rpc</groupId>
	<artifactId>jboss-jaxrpc-api_1.1_spec</artifactId>
	<version>1.0.1.Final</version>
	<scope>test</scope>
</dependency>

Now the test works fine.
With my own dummy.
EJB:

@Stateless
@Remote
public class ejbBean implements EjbBean {
	@PersistenceContext
	private EntityManager em;
	private SessionContext ctx;
 
	@Resource
	void setSessionContext(SessionContext ctx) {
		this.ctx = ctx;
	}
 
	public String someMethod() {
		String name = ctx.getCallerPrincipal().getName();
		return name;
	}
}

Dummy:

public class DummySessionContext implements SessionContext {
...
	@Override
	public Principal getCallerPrincipal() {
		// TODO Auto-generated method stub
		Principal principal = () -> "TESTUSER";
		return principal;
	}
...	
}

TEST:

public class EjbBeanTest {
	@Rule
	public final MockitoRule mockitoRule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
	@Mock
	private EntityManager em;
 
 
	@InjectMocks
	private EjbBean cut;
 
	@Before
	public void setUp() {
		cut.setSessionContext(new DummySessionContext());
	}
 
	@Test
	public void test() {
		String result = cut.someMethod();
		assertEquals("TestUser", result);
	}
}

Furthermore I tried to mock again.
And now this works too.

EJB:

@Stateless
@Remote
public class ejbBean implements EjbBean {
	@PersistenceContext
	private EntityManager em;
	@Resource
	private SessionContext ctx;
 
	public String someMethod() {
		String name = ctx.getCallerPrincipal().getName();
		return name;
	}
}

TEST:

public class EjbBeanTest {
	@Rule
	public final MockitoRule mockitoRule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
	@Mock
	private EntityManager em;
	@Mock
	private SessionContext ctx;
 
	@InjectMocks
	private EjbBean cut;
 
 
	@Test
	public void test() { 
		Principal p = mock(Principal.class);
		when(ctx.getCallerPrincipal()).thenReturn(p);
		when(p.getName()).thenReturn("TestUser");
 
		String result = cut.someMethod();
		assertEquals("TestUser", result);
	}
}

Conclusion
I my case using the mockito hides the missing dependency. And I had a hard time to figure it out.
Many thanks to my friend and Sensai Jiri.

SVN – Branch aktuell halten

Branch aktuell halten.

Wenn wir in einem Entwicklungsbranch arbeiten sollte regelmäßig (oft) der Trunk-Head in den Entwicklungsbranch gemerged werden. Damit sich die Zweige nicht zu weit von einander entfernen.

In unserem Fall nehmen wir immer die letzte Tag version. Also die letzte released Version des Trunks. So lange wir also in einem Entwicklungsbranch parallel zum Trunk arbeiten sollten nach einem Release alle Changes in den Entwicklungsbranch einfließen.

All changes that are going to be committed to Trunk, must be applied to all changes already committed to Trunk, before those changes are merged into Trunk.

Quelle:https://designbygravity.wordpress.com/2009/10/19/what-mother-never-told-you-about-svn-branching-and-merging/

Vorausetzung am Bsp. Entwicklungsbranch GUI

Der Entwicklungsbrunch ist ausgecheckt und upgedatet und liegt als „saubere“ working copy im Eclipse Workspace.

Das heißt keine Datei hat ein Change welcher nicht eingecheckt ist. (Kein Sternchen)

Schritt-für-Schritt-Anleitung

  1. bei allen pom.xml´s die Version von 8.x.0-GUI-SNAPSHOT auf die neue Version 8.x.0 ändern (bspsw. 8.4.0-GUI-SNAPSHOT auf 8.5.0)
    Damit wir nicht soviele Mergekonflikte in den pom.xml´s bekommen die sich nur auf die Versionsnummer beziehen.
  2. nicht commiten
  3. Rechtsklick auf dem Projektordner in Eclipse -> Team -> Merge
    image2015-7-7-14-40-38
  4. In dem folgenden Screen das Diff auswählen was gemerged werden soll. Also die letzte Version wo der Trunk gemerged wurde (hier Tag 8.0.0) bis zu der Version die released wurde (Tag 8.1.0)
    Ziel ist unsere Working Copy!
    image2015-7-7-14-48-46
  5. Nun alle Konflikte manuell aufheben.
  6. nicht commiten.
  7. in allen poms die Version wieder ändern auf 8.x.0-GUI-SNAPSHOT
    image2015-7-7-14-56-12
  8. Dann einchecken und commit mit merged version 8.x.0 beschreiben.
    Nun haben wir im Branch den selben Entwicklungsstand wie die letzte release Version. Alle Änderungen aus der Trunkentwicklung sind vorhanden.
  9. Projekt (GUI) in Jenkins bauen.

Add Admob jar to local Maven Repository

I do not find the dependency declaration for googles Admob at Maven Central.
Download the jar https://developers.google.com/mobile-ads-sdk/download#downloadandroid
Install AdMob in my local m2 Repository to use the Dependency

ingoreschke$cd Downloads/GoogleAdMobAdsSdkAndroid-6.4.1/
ingoreschke$ mvn install:install-file -Dfile=GoogleAdMobAdsSdk-6.4.1.jar 
-DgroupId=com.google.ads
-DartifactId=admob 
-Dversion=6.4.1 
-Dpackaging=jar

refer it in your pom using

<dependency>
	<groupId>com.google.ads</groupId>
	<artifactId>admob</artifactId>
	<version>6.4.1</version>
</dependency>

Source:
http://stackoverflow.com/questions/12873586/how-to-download-and-install-jar-in-my-local-repo-maven

Alternativly you can create a helper POM in same directory

<?xml version="1.0" encoding="UTF-8"?>
 
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>de.ingoreschke</groupId>
    <artifactId>install-admob</artifactId>
    <version>1.0.0</version>
    <!--Helper POM for installing admob to local repo-->
    <build>
        <defaultGoal>install:install-file</defaultGoal>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-install-plugin</artifactId>
                <version>2.5</version>
                <configuration>
                    <file>GoogleAdMobAdsSdk-6.4.1.jar</file>
                    <groupId>com.google.ads</groupId>
                    <artifactId>admob</artifactId>
                    <packaging>jar</packaging>
                    <version>6.4.1</version>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

call mvn

mvn

Source:
http://www.michenux.net/android-admob-tutorial-461.html

maven android eclipse

prerequired:

  • Maven3 installed
  • Eclipse 3.7 or greater
  • maven – plugin
  • android plugin

create sturcture with maven.
Terminal:
go to Project Folder.

mvn archetype:generate | grep android
46: remote -&gt; com.googlecode.android-player-root-archetype:parent-archetype (-)
110: remote -&gt; com.vektorsoft.demux.tools:demux-android-archetype (Create Android application structure for DEMUX Framework applications)
117: remote -&gt; de.akquinet.android.archetypes:android-gcm-quickstart (Creates a skeleton for a GCM Android application)
118: remote -&gt; de.akquinet.android.archetypes:android-library-quickstart (Creates a skeleton for an Android library)
119: remote -&gt; de.akquinet.android.archetypes:android-quickstart (Creates a skeleton for an Android application)
120: remote -&gt; de.akquinet.android.archetypes:android-release (Creates a skeleton for an Android application,
121: remote -&gt; de.akquinet.android.archetypes:android-with-test (Creates a skeleton for an Android application and instrumentation tests)
122: remote -&gt; de.akquinet.android.archetypes:stand-archetype (Creates a skeleton for an Android application using the Stand framework stack)
531: remote -&gt; org.eclipse.xtend:xtend-android-archetype (-)
826: remote -&gt; ru.nikitav.android.archetypes:release (-)
827: remote -&gt; ru.nikitav.android.archetypes:release-robolectric (-)
^C

Keep ID 119 in mind and enter it.

Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 296: 119

Choose a version (latest recommend)

Choose de.akquinet.android.archetypes:android-quickstart version: 
1: 1.0.0
2: 1.0.1
3: 1.0.2
4: 1.0.3
5: 1.0.4
6: 1.0.5
7: 1.0.6
8: 1.0.7
9: 1.0.8
10: 1.0.9
11: 1.0.10
12: 1.0.11

Define a groupId, artefactId, version, package etc. and confirm with Y:

Define value for property 'groupId': : de.ingoreschke.annuitycalculator
Define value for property 'artifactId': : app-full
Define value for property 'version':  1.0-SNAPSHOT: : 1.0.0
Define value for property 'package':  de.ingoreschke.annuitycalculator: : de.ingoreschke.annuitycalculator.full
Define value for property 'android-plugin-version':  3.6.0: : 
Define value for property 'emulator':  not-specified: : 
Define value for property 'platform':  16: : 17
Confirm properties configuration:
groupId: de.ingoreschke.annuitycalculator
artifactId: app-full
version: 1.0.0
package: de.ingoreschke.annuitycalculator.full
android-plugin-version: 3.6.0
emulator: not-specified
platform: 16

New Module in Main pom.xml

<?xml version="1.0" encoding="UTF-8"?>
  2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.o
  3   <modelVersion>4.0.0</modelVersion>
  4   <groupId>de.ingoreschke</groupId>
  5   <artifactId>annuitycalculator</artifactId>
  6   <version>0.0.1-SNAPSHOT</version>
  7   <packaging>pom</packaging>
  8   <name>Main Project Folder</name>
  9   <description>This will be hold all sub projects Android, Java, Website to Annuity Calculator Project</description>
 10   <modules>
 11     <module>core</module>
 12     <module>app_full</module>
 13   </modules>
 14 </project>

Pom.xml in new Project app_full

<?xml version="1.0" encoding="UTF-8"?>
  2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.o
  3     <modelVersion>4.0.0</modelVersion>
  4     <parent>
  5     <artifactId>annuitycalculator</artifactId>
  6     <groupId>de.ingoreschke</groupId>
  7     <version>0.0.1-SNAPSHOT</version>
  8   </parent>
  9     <groupId>de.ingoreschke.annuitycalculator</groupId>
 10     <artifactId>app_full</artifactId>
 11     <version>1.0-SNAPSHOT</version>
 12     <packaging>apk</packaging>
 13     <name>app_full</name>
 14     <properties>
 15         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 16         <platform.version>4.1.1.4</platform.version>
 17         <android.plugin.version>3.6.0</android.plugin.version>
 18     </properties>
 19     <dependencies>
 20         <dependency>
 21             <groupId>com.google.android</groupId>
 22             <artifactId>android</artifactId>
 23             <version>${platform.version}</version>
 24             <scope>provided</scope>
 25         </dependency>
 26     </dependencies>
 27     <build>
 28         <finalName>${project.artifactId}</finalName>
 29         <pluginManagement>
 30             <plugins>
 31                 <plugin>
 32                     <groupId>com.jayway.maven.plugins.android.generation2</groupId>
 33                     <artifactId>android-maven-plugin</artifactId>
 34                     <version>${android.plugin.version}</version>
 35                     <extensions>true</extensions>
 36                 </plugin>
 37             </plugins>
 38         </pluginManagement>
 39         <plugins>
 40             <plugin>
 41                 <groupId>com.jayway.maven.plugins.android.generation2</groupId>
 42                 <artifactId>android-maven-plugin</artifactId>
 43                 <configuration>
 44                     <sdk>
 45                         <platform>16</platform>
 46                     </sdk>
 47                 </configuration>
 48             </plugin>
 49         </plugins>
 50     </build>
 51 </project>
<pre>
 
<pre lang="bash">mvn clean install

In Eclipse
Import the new Maven Modul.
After Import I got a Error:
Project 'app_full' is missing required source folder: 'src/test/java'
Fixed it by adding a folder test/java into src.
Bildschirmfoto 2013-09-11 um 00.28.35

Source: a screencast found on youtube. http://www.youtube.com/watch?v=S7XDsivkVUA

TDD Test aufräumen

Es ist generell wichtig nach einem unit Test den Code aufzuräumen, also angelegte Daten wieder zu löschen. z. B. Testdaten in einer Datenbank.

Aber noch wichtiger ist es vor einem unit test aufzuräumen.

Damit wenn bspw. während eines vorherigen Testlauf etwas schief ging und der Test nicht bis zu Ende durch gelaufen ist und somit noch Testdaten in der DB liegen, der nächste Test ordentlich und sauber durchgeführt werden kann.

Merkhilfe für gutes Design

1) Switch-Konstrukte oder nicht-elementare if-Statements (alles, was nicht mit <,>=,==,|| etc geprüft wird)
weisen auf einen Design-Fehler hin, den man durch Polymorphismus lösen kann. Bsp: Methode male() vor und nach Benutzung von abstrakten Methoden
2) Vererbte Dinge sind immer in den Unterklassen da, aber nur public v/m sind echt „sichtbar“
3) Man verwendet immer private für Attribute einer Klasse und macht sich Getter/Setter um in Unterklassen (und evtl auch aus anderen Klassen) darauf zugreifen zu können
4) Vererben tut man, wenn verschiedene Objekte in Teilen gleich sind und sich gleich Verhalten
5) Abstrakte Klassen nutzt man, wenn es die Oberklasse an sich gar nicht gibt
6) Abstrakte Methoden nutzt man dann, wenn man vererben möchte, die Funktionalitäten aber in jeder Unterklasse anders implementiert werden müssen, und nicht gleich sind.
7) die Implementierung eines Interfaces ist sowas wie das Implementieren von abstrakten Methoden einer Superklasse, nur besser!

Gefunden hier:
Quelle: http://www.java-forum.org/einfuehrungen-erste-schritte/76834-vererbung-polymorphie.html

Eigene Java Klassen in Coldfusion verwenden

Coldfusion ist ein Javaframework. Deshalb kann man aus Coldfusion heraus auch auf Javaklassen zugreifen. Z.B.

<cfset a = [1, 2, 3, 4, 5, 12,23,33,45]>
<cfdump var="#a#">
<cfoutput>reverse it</cfoutput>
<cfset createObject("java", "java.util.Collections").reverse(a)>
<cfdump var="#a#">

Um eigene Javaklassen zu bauen und unter Coldfusion anzusprechen muß folgendes gemacht werden.

Schritt für Schritt:
1) Javaklasse anlegen (natürlich im package)

package de.ingoreschke.simplemath;
 
public class SimpleMath {
	public int addInt(int a, int b){
		return a + b;
	}
}

2) Jar File erstellen
Unter eclipse geht das relative einfach.
auf das

  • package rechte Maustaste
  • Export
  • type Jar file wählen
  • Ziel angeben

Eclipse macht den Rest.

3) Jar File in den Classpath einbinden. Und das ist eine Wissenschaft für sich 😉
Siehe dazu Guide to set classpath
In kurzform

  • das Jar File in das WEB-INF/lib Verzeichnis kopieren
  • Server durchstarten
  • 4) Klasse mit vollqualifizierten Namen aufrufen

    <cfset myObj = createObject("java", "de.ingoreschke.simplemath.SimpleMath")>
    <cfset val1 = 3>
    <cfset val2 = 34>
    <cfset result = myObj.addInt(val1,val2)>
     
    <cfoutput>
    Das Ergebnis von #val1# + #val2# = #result#
    </cfoutput>

    Quellen und nützliche Ausführungen:
    ColdFusion’s Java connection
    Guide to set classpath

Delegation vor Vererbung

Vererbung ist ein tolles Mittel, um bereits modelliertes Verhalten vorhandener Klassen ohne Copy-Paste-Ansatz wiederzuverwenden. Jedoch eine Vererbung die nur dem Zweck dient, keinen Sourcecode zu duplizieren führt fast immer zu unsinnigen oder zumindest zweifelhaften Design und wird Implementierungsvererbung genannt. Die entstehende Klasse wiederspricht (in der Regel) dem Konzept des Subtyps. Gemeinsam verwendbare Funktionalität sollte besser in seperate Hilfsklassen ausgelagert werden und dann per Delegation statt Vererbung angesprochen werden.

Wird Vererbung nur eingesetzt, wenn tatsächlich die is-a Beziehung erfüllt ist, so profitiert man davon, dass beim Aufbau einer Klassenhierachie durch Ableitung lediglich die Unterschiede zum vererbten Verhalten und Zustand definiert werden müssen.

Delegation beschreibt, dass eine Aufgabe einem anderen Programmteil übergeben wird. In diesem Fall ist damit gemeint, das eine Klasse eine andere über eine Assoziation kennt und deren Methoden aufruft.

 

Quelle: „Auf dem Weg zum Java Profi“ – Seite 50.

Siehe auch
http://clean-code-developer.de/Roter-Grad.ashx#Favour_Composition_over_Inheritance_FCoI_3