2014-03-27

ARM med Genymotion

Om man kör den senaste versionen av Android-emulatorn Genymotion - som jag rekommenderar då den är både snabb och gratis - så kan man stöta på patrull om man försöker använda sig av bibliotek som är specifikt kompilerade för ARM-processorn (som de flesta mobila enheter använder). Detta händer på Windows, vet inte hur det är i Äpplevärlden.

Felmedelandet i Logcat lyder "Installation error: INSTALL_FAILED_CPU_ABI_INCOMPATIBLE". Jag stötte på detta då jag använde ARM-kompilerad kod skriven i C++ i ett skanningsbibliotek, men det kan bli samma visa om man utvecklar spel.

Man fixar detta genom att ladda ner följande filer: http://www.mirrorcreator.com/files/0ZIO8PME/Genymotion-ARM-Translation_v1.1.zip_links
Sen drar man filerna till Genymotions emulatorfönster (emulatorn måste alltså vara startad) och släpper dem på emulatorns "skärm". Man får en fråga om man vill flasha sin emulator, svara OK, vänta, och starta om emulatorn. Nu skall det funka att slänga på ARM-kompilerade bibliotek på din emulator.

2014-01-10

Blob problem med MySql och Spring MVC

Jag hade problem med en bild som är lagrad i en MySql databas och var lagrad med datatypen Blob.
Problemet var att bilden vägrade visa sig på sidan. Lösningen var att importera rätt paket och att mappa rätt url i din jsp sida.

Istället för java.jdbc.sql.Blob; skulle det vara java.sql.Blob;

Hela lösningen;

1. Spara ner bilden med datatypen Blob i din domänklass :

@Column(name = "image")
@Lob
private Blob image;

2. Hämta den blob objektet genom att hämta hela objektet som den ligger i mitt fall i en Person :

@Override
public Person getPerson(int personId) {
return (Person)session.getCurrentSession().get(Person.class, personId);
}

3. Hämta den via en service och lägg upp den i din Controller.

@RequestMapping(value = "/image/{id}", method = RequestMethod.GET)
public String viewImages(@PathVariable int id, HttpServletResponse response) throws SQLException {

Person person = service.getPerson(id);
Blob blob = person.getImage();

try {
         
            OutputStream out = response.getOutputStream();
            response.setContentType("image/JPEG");
            IOUtils.copy(person.getImage().getBinaryStream(), out);
            log.trace(person.getImage().getBytes(1, (int) blob.length()));
            out.flush();
            out.close();
       
        } catch (IOException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
       
       
        return null;
    }


Obs bilder måste ha en egen kontroller eftersom din jsp behöver en <img src="url">.

4. Lägg till den i din .jsp

<td><img src= "<%= request.getContextPath() %>/image/${person.id}.html"/></td>

Slutresultatet :





2013-12-15

Loopia + Gmail = problem!

Vi reggade ett domännamn och webhotell på loopia.se för få en egen mail-adress. Den mail-adressen var tänkt att användas för att programmatiskt skicka ut mail till användarna från servern.
När vi provkörde detta visade det sig att mailen aldrig kom fram till @gmail.com-adresser. Anledningen är att folk har missbrukat loopia-mailen till att skicka ut spam. Som resultat av det har dom större företagen (Google bla) blockat alla inkommande mail ifrån loopia vilket gör att mailen inte kommer fram alls.

Slutsats. Använd dig INTE av loopia om du söker en tjänst för att regga en egen mail-adress att skicka mail ifrån. Vill bara upplysa er om detta då det säkert är någon mer där ute som någon gång kommer behöva välja ett företag att regga domän hos.

Lösningen på detta vet jag inte än. Loopia vägrar betala tillbaka pengarna.
Postar här om jag hittar en "work around" på problemet.

2013-12-13

NullPointerException vid login


*Moderator*'
Håll inläggen korta och relevanta.

Om ni har två tabeller i ett schema som har beroenden till varandra, se då till att rensa båda då det annars  finns risk för ett NullPointerException.
Detta är bara förslag på förändring. Du får själv redigera det. Men håll det kort och informationsrikt det skall gå fort att förstå problemet och lösningen.


*Slut*


Vi hade en gästbok med en login funktion. Till gästboken fanns det användare och meddelanden som sparades i en databas. Varje användare hade ett username och ett id och varje meddelande hade en text och ett id kopplat till användaren. Plötsligt efter att ha hashat och saltat lösenorden i databasen  så fick jag ett nullPointerException.

Felet låg i att jag hade rensat bort allt gammalt i min users tabell i databasen eftersom det såg fult ut med både hashade lösenord och icke hashade lösenord. Men jag hade inte rensat i meddelandetabellen vilket gjorde att där fanns meddelanden från userId 3 och 4 medans jag i min users tabell hade bara två stycken användare sparade. Detta skapade mitt nullPoiterException.
Så vi kan lära oss av detta att om vi har flera tabeller med kolumner som hör ihop glöm inte att rensa den datan också annars kommer ett exception att kastas. 

2013-12-11

Missing artifact jdk.tools:jdk.tools:jar:1.6 /Maven

Detta felmeddelande uppstod när ett nytt dependecy lades till i föräldrapomen.
Dependecyt i detta faller var Solr-core.

Lösning: Problemet grundar sig i att Maven versionerna till Linux och Windows inte kompileras med java tools till skillnad från Mac. En lösning för problemet är att helt enkelt lägga in ett dependency för detta i sin parent pom. Denna lösningen fungerar dock bara om man håller sig till en plattform. Alltså utvecklar man på olika plattformar så kommer det att sluta fungera på Mac.
Lösning på detta kommer komma inom kort.

Java tools dependency

<dependency>
  <groupId>com.sun</groupId>
  <artifactId>tools</artifactId>
  <scope>system</scope>
  <systemPath>${java.home}/lib/tools.jar</systemPath>
</dependency>

Lösning 2:

Som nämnt tidigare så ligger problemet i att tools.jar inte följer med trotts att den finns som standard i samtliga JDK utgåvor som finns att få tag på.

Efter tips från ett pro(Bertil) så fick vi reda på att vi skulle försöka undvika att det kompileras olika beroende på vilket system man sitter på. Detta är något man kan lösa genom att bygga olika profiler beroende på vilket OS man sitter på (men detta är alltså inte att rekommendera).

Det man måste göra är att peka på rätt VM (Virtual machine)
Ett sätt att göra detta på är att ändra i sin IDE. I detta fallet är det Eclipse.

I mappen där man packat upp Eclipse finns det en fil som heter eclipse.ini, man får redigera den till att se ut så här (Självklart med sin egen path till sin JDK) Det viktiga i texten nedan är markerat.

-startup
plugins/org.eclipse.equinox.launcher_1.3.0.v20130327-1440.jar
--launcher.library
plugins/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.1.200.v20130521-0416
-product
org.eclipse.epp.package.jee.product
--launcher.defaultAction
openFile
-showsplash
org.eclipse.platform
--launcher.XXMaxPermSize
256m
--launcher.defaultAction
openFile
--launcher.appendVmargs
-vm
/usr/lib/jvm/jdk1.7.0_25/bin/java
-vmargs
-Dosgi.requiredJavaVersion=1.6
-XX:MaxPermSize=256m
-Xms40m
-Xmx512m



Vill tacka Bertil för hjälp och tips angående detta problem.

OutOfMemoryError

Det verkar som att alla vägar bär till Rom i frågan om hur man löser OutOfMemoryError  - Java heap Space. Vissa krångligare än andra men detta löste i alla fall mitt problem och är väldigt enkelt.

JVM behöver mer RAM för att kunna köras och det kan ställas in i eclipse.

1. Windows ->preferences (mac: eclipse -> preferences)
2. Java - Installed JREs
3. Välj JRE och klicka på Edit
4. Vid default VM argument fältet skriv in -Xmx1024M. (Eller mindre än 1024)
5. Tryck på finish.

DONE!

2013-12-10

Easymock tutorial

I skolan har vi använt oss en del av något som kallas Easymock och det tog mig ett tag att förstå mig på hur det fungerar. 
Easymock är ett sätt att testa en viss del av koden som har beroenden till andra delar. Easymockning fungerar som en bandspelare:  man spelar in något och man spelar upp något.


I vårt exempel så har vi endast en service som är beroende av ett repository. Vi struntar i databasen, men jag har ändå med den på bilden för att få lite mer förståelse.
Nu har vi metoder i våran service som vi vill testa att de fungerar, men servicen har ett beroende till vårat repository och vi vill enbart testa services. Detta löser vi genom att mocka bort vårt repository.

Först vill jag visa bara hur metoden ser ut som vi skall testa. 

@Service
public class PersonServiceImpl implements PersonService {

 @Autowired
 private PersonRepository personRepository;

 public Person createPerson(Person person) {
  
  long id = personRepository.createPerson(person); 
  return personRepository.getPerson(id);
 }

Som du ser har vi ett anrop till vårat repository där logiken ligger för att kunna skapa vår person. Detta beroendet måste vi mocka bort.

Vad man gör med Eaymock är att man först spelar in ett scenario med mockning och sedan spelar man upp det.

Låt oss titta på detta. 

public class PersonServiceTest {
 
 @Test
 public void testCreatePerson() {
  
  PersonRepository repo = EasyMock.createMock(PersonRepository.class);
  Person person = new Person("Arne", "Anka", "arne@anka.com", "07605050", "");
  EasyMock.expect(repo.createPerson(person)).andReturn(1l);
  EasyMock.expect(repo.getPerson(1l)).andReturn(person);
  EasyMock.replay(repo);
  
  PersonServiceImpl service = new PersonServiceImpl();
  service.setPersonRepository(repo);
  Person newPerson = service.createPerson(person);
  
  assertEquals("Created Person", person, newPerson);
    
 }
Det första som sker är att vi skapar själva mocken som vi vill göra oss oberoende av. Detta görs genom följande kod : EasyMock.createMock(PersonRepository.class);
Efter vi har gjort det så spelar vi in vårt scenario vi fejkar alltså vårt repo.
Eftersom vi skall skapa en Person så börjar vi med att skapa en person och skickar in värden.
När vi skapat en person vill vi använda vår createPerson metod i repot som vi mockar.
EasyMock.expect(repo.createPerson(person)).andReturn(1l);

expect innebär att det är en metod med ett retur värde och vi skickar in vårt egna värde, kan vara precis vad som helst men det måste vara samma datatyp som finns i metoden. I detta fall är det värde 1 som vi väljer av typen long. .andReturn(1l) behövs eftersom metoden vi testar returnerar ett värde. Så vi returnerar samma värde som vi skickade in.
Om du inte har en retur metod behöver du inte skriva expect och inte andReturn efteråt utan du skriver bara repo.cretePerson();
Efter vi har fejkat alla anrop vi behöver så spelar vi in hela scenariot genom att skriva :  EasyMock.replay(repo).
Nu vill vi spela upp alltihopa och testa vår Service.

                PersonServiceImpl service = new PersonServiceImpl();
  service.setPersonRepository(repo);
  Person newPerson = service.createPerson(person);

Vi skapar en referens till vår service och sätter repot som vår service.
Efter det så skapar vi vår person som är det vi har velat testa hela tiden.
Slutligen kör vi själva testet

assertEquals("Created Person", person, newPerson);