onsdagen den 2:e november 2011

Java på OSX Lion

Om man vill köra Java 1.4 eller 1.5 i OSX Lion är det inte mycket att göra åt om man inte råkar komma över en variant av Leopard-tar.gz filerna för dessa. Sen kan man ju passa på att stoppa in dessa i OSX Frameworkkatalog och länka till dessa istället för att låta länkarna peka på 1.6.  

tar xzvf java.1.4.2-leopard.tar.gz
sudo mv 1.4.2 /System/Library/Frameworks/JavaVM.framework/Versions/1.4.2-leopard
sudo rm /System/Library/Frameworks/JavaVM.framework/Versions/1.4
sudo rm /System/Library/Frameworks/JavaVM.framework/Versions/1.4.2
sudo ln -s /System/Library/Frameworks/JavaVM.framework/Versions/1.4.2-leopard/ /System/Library/Frameworks/JavaVM.framework/Versions/1.4.2
sudo ln -s /System/Library/Frameworks/JavaVM.framework/Versions/1.4.2 /System/Library/Frameworks/JavaVM.framework/Versions/1.4.2

tar xzvf java.1.5.0-leopard.tar.gz 
sudo mv 1.5.0 /System/Library/Frameworks/JavaVM.framework/Versions/1.5.0-leopard
sudo rm /System/Library/Frameworks/JavaVM.framework/Versions/1.5
sudo rm /System/Library/Frameworks/JavaVM.framework/Versions/1.5.0
sudo ln -s /System/Library/Frameworks/JavaVM.framework/Versions/1.5.0-leopard /System/Library/Frameworks/JavaVM.framework/Versions/1.5.0
sudo ln -s /System/Library/Frameworks/JavaVM.framework/Versions/1.5.0 /System/Library/Frameworks/JavaVM.framework/Versions/1.5

... och bob är din onkel.

torsdagen den 6:e oktober 2011

Oracle XA

Eftersom det visade sig vara så att man måste granta rättigheter för att köra XA transaktioner på en Oracledatabas från en jboss så passar jag på att påminna mig själv om att det krävs för din dbuser som jag ska köra med från appservern.
Om man inte gör det dyker detta mysiga felmeddelande upp som en varning i loggen med cirka 3 minuters mellanrum.
2011-10-06 23:31:45,099 WARN  [com.arjuna.ats.jta.logging.loggerI18N] (Thread-12) [com.arjuna.ats.internal.jta.recovery.xarecovery1] Local XARecoveryModule.xaRecovery  got XA exception javax.transaction.xa.XAException, XAException.XAER_RMERR

Så passa på du med, granta dig själv till en bättre värld.
GRANT SELECT ON sys.dba_pending_transactions TO <dbuser>;
GRANT SELECT ON sys.pending_trans$ TO <dbuser>;
GRANT SELECT ON sys.dba_2pc_pending TO <dbuser>;
GRANT EXECUTE ON sys.dbms_system TO <dbuser>;

onsdagen den 23:e mars 2011

Hotswappa sessioncontext i en ejb2-böna med spring.

Eftersom jag för andra gången glömde bort hur man sätter upp en fin liten hotswappable target source för att swappa in sessionskontextet i en gammal böna tänkte jag att jag lägger upp en liten komihåg på det nu.

Först tar vi och lägger till ett target i sessionsbönan vi ska swappa den från:

public class Bean extends AbstractStatelessSessionBean implements SessionBean {
private HotSwappableTargetSource sessionContextTarget;
protected void onEjbCreate() throws CreateException {
BeanFactory beanFactory = getBeanFactory();
sessionContextTarget = = (HotSwappableTargetSource) beanFactory.getBean("hotswappableSessionContext");
}
}

samt att vi lägger till själva swappen i set-metoden:
@Override
public void setSessionContext(SessionContext sessionContext) {
super.setSessionContext(sessionContext);
this.sessionContextTarget.swap(sessionContext);
}

Därefer passar vi på att konfigurera den i springxmlen,

<bean id="sessionContextBean" class="nu.danielsundberg.FejkSessionContext"/>
<bean id="hotswappableSessionContext" class="org.springframework.aop.target.HotSwappableTargetSource">
<constructor-arg><ref local="sessionContextBean"/></constructor-arg>
</bean> 

lägger till den injectad i vår andra böna vi vill ha access till contextet i
<property name="sessionsContext">
<ref local="sessionContextBean"/>
</property>
och avslutar med att lägga till den i mottagande bönan.
private SessionContext sessionsContext;
public void setSessionsContext(SessionContext sessionsContext) {
this.sessionsContext = sessionsContext;
}

Och bob är min onkel.

måndagen den 1:e november 2010

@Hide på metoder i Android

Efter att ha letat oavbrutet i ungefär 2 timmar efter vettiga (eller på något sätt befintliga) sätt att tjuvtitta på en befintlig ström mot Audioslinger (Androids underliggande tjusiga ramverk som skjuter data på ljudhårdvaran) som man inte skapat själv i Androids medialibbar så har jag kommit fram till följande.

  1. Androids medialibbar suger hästdelar.
  2. Allt bra "kommer sen" (i det här fallet Open AL och mer native-nära funktioner)

Så tills vidare trodde jag förstås att jag var, som undomarna säger idag, rökt. Men av en magisk slump (eller idogt googlande) landade jag på implementationen av de medföljande visualiseringarna av musik i Androidkällkoden, där en metod med namnet "snoop"användes flitigt på mediaspelarklassen som jag ansåg vara värd en extra titt. Efter att ha förundrats över det faktum att jag tydligen inte kunde anropa denna fina metod (eller ens bevisa dess existens i min utvecklingsmiljö) fick jag en snabb lektion i en annotering med det snillrika namnet @Hide. Denna annotering används på metoder som inte anses vara dokumenterbar/förvaltningsbar i Androids källkod (men förmodligen kommer att bli det iom att den finns kvar). Eftersom jag inte har lust att kompilera några stubbar/bygga om Androidprylar från source kom jag raskt att tänka på perfektionen i att reflektera. Så utan mera omsvävningar, här kommer hur du anropar en metod i Android (förslagsvis snoopmetoden på MediaPlayer i det här fallet) på ett mer eller mindre tjusigt sätt tills den slutar gömmas:
short [] mVizData = new short[1024];
try {
  Class<MediaPlayer> myEvilMediaPlayer = (Class<MediaPlayer>) Class.forName(MediaPlayer.class.getName());
  try {
    Class[] parameterTypes = new Class[] {short[].class, int.class};
    Method snoop = myEvilMediaPlayer.getMethod("snoop", parameterTypes);
    snoop.setAccessible(true);
    Object[] arguments = new Object[2];
    arguments[0] = mVizData;
    arguments[1] = 0;
    int x = (Integer) snoop.invoke(myEvilMediaPlayer, arguments);
    System.out.println(x);
  } catch (SecurityException e) {
    e.printStackTrace();
  } catch (NoSuchMethodException e) {
    e.printStackTrace();
  } catch (IllegalArgumentException e) {
    e.printStackTrace();
  } catch (IllegalAccessException e) {
    e.printStackTrace();
  } catch (InvocationTargetException e) {
    e.printStackTrace();
  }
} catch (ClassNotFoundException e) {
  e.printStackTrace();
}
In your face @Hide annoteringen, det där är vad man får om man försöker gömma metoder för folk.

tisdagen den 19:e oktober 2010

Ternary operators i Java

Okej, jag kan vara lätt kod-fascistisk ibland, och jag uppskattar ett fläskigt syntax-solo lika mycket som the next nerd, men ternary operators, eller shorthand eller the child ny any other name osv borde avskaffas omedelbart i kod som skall läsas av många människor. Jag är ju ogärna gnällig men efter att ha stött på detta fenomen som kräver massor av tid varje gång av mig (eftersom det inte är direkt uppenbart vad ditt statement gör så måste jag naturligtvis läsa det och tolka det) så tänkte jag att jag bloggar en liten kommihåglapp så jag kan översätta snabbare.

Ta exemplet
minVal = (a < b) ? a : b;
där vi trivialt sätter det minsta av 2 värden (a och b då i det här fallet) till minVal. Motsvarande vanlig ifsats borde typiskt vara
if ( a < b ) { minVal = a; } else { minVal = b; }
men det är ju helt förkastligt att skriva om man vill imponera på folk med sin syntax-skill. Vilket natruligtvis är häftigt i nördsammanhang där och då, men när nyanställda putte ska laga ett PMD-fel från cruisecontrollen och hittar en lång jäkla harrang som han inte riktigt hänger med i så öppnar man ju upp för skapande av ett fel i koden som enbart beror på att man inte kunde kamma sig och skriva en vanlig bond-ifsats istället.

Naturligtvis är det inte fel att använda denna fina funktion som Sun stoppat in i specen, men jag skulle säga att det nog kan tänkas vara moraliskt snarare än tekniskt. Generellt så funkar det iaf så här
resultat = test ? värde1 : värde2;
eller med if/else
if ( test ) { resultat = värde1; } else { resultat = värde2; }
så det är ju förstås inte helt svårt när man väl vänjer sig. Ett bra exempel taget ur vanliga livet (något förvanskat förstås men ändå) är följande.
Iterable<Grupp> kanskeTom = listaMedPoster.iterator().hasNext() ? listaMedPoster : Arrays.asList(Grupp.EMPTY);

och efter en städning (fick PMD-warnings på raden)
Iterable<Grupp> kanskeTom = null; 
if(listaMedPoster.iterator().hasNext()) {  
    kanskeTom = listaMedPoster 
} else 
    kanskeTom = Arrays.asList(Grupp.EMPTY);  
så nästa gång du funderar på att köra shorthand, tänk på mig som istället för att skumma igenom din kod kommer behöva tänka flera sekunder till på din ifsats.

torsdagen den 7:e oktober 2010

Android och IPSec/L2TP på Ubuntu.

Efter att ha trollat med att sätta upp en VPN som min telefon kan använda kan jag lätt konstatera att det inte fanns så där jättemånga "bra" howtos på teh internets. Så här gjorde jag.

1. Installera/configurera Openswan
För att kryptera IP-paketen vill vi installera Openswan som tillhandahåller kryptering och autentifiering för att skeppa paket mellan din enhet och din server. Här kör alla Openswan så det gjorde jag med.
sudo aptitude install openswan

och därefter så passade jag på att stoppa in följande i min /etc/ipsec.conf :

version 2.0
config setup
nat_traversal=yes
virtual_private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12
oe=off
protostack=netkey

conn L2TP-PSK-NAT
rightsubnet=vhost:%priv
also=L2TP-PSK-noNAT

conn L2TP-PSK-noNAT
authby=secret
pfs=no
auto=add
keyingtries=3
rekey=no
ikelifetime=8h
keylife=1h
type=transport
left=VPNSERVERNS.INTERNA.IP
leftprotoport=17/1701
right=%any
rightprotoport=17/%any

och passade därefter på att sätta lösenordet för att kryptera paket in till mitt fina intranät genom att skriva följande i min /etc/ipsec.secrets :

VPNSERVERNS.INTERNA.IP %any: PSK MITT LÖSENORD

och eftersom Openswan gnällde en hel massa på diverse så passade jag på att köra följande kommando i mitt fina shell :

for each in /proc/sys/net/ipv4/conf/*
do
echo 0 > $each/accept_redirects
echo 0 > $each/send_redirects
done

och därefter så verifierade jag att allt var ok och därefter starta om Openswan genom att yppa de magiska orden (tillsammans med en magisk gest) :

sudo ipsec verify
sudo /etc/init.d/ipsec restart

Om man har lust att se vad som händer så visas helt magiskt allt som händer i detta sammanhang i loggen /var/log/syslog. Leta efter det magiska IPSec connection established.

2. Installera/konfigurera L2TP
L2TP är alltså delen som tunnlar data från din klient till ditt säkra nät. Det krypterar inte och det autentifierar inte (vilket är typ anledningen till att man måste köra IPSec framför, vilket alla, läs microsoft och apple, undviker att tänka på).

Hur som helst, installera paketet xl2tp från en apt nära dig :

sudo aptitude install xl2tpd

och konfigurera i en trevlig fil som heter /etc/xl2tpd/xl2tpd.conf :


[global]
ipsec saref = yes

[lns default]
ip range = 10.1.2.2-10.1.2.255
local ip = 10.1.2.1
refuse chap = yes
refuse pap = yes
require authentication = yes
ppp debug = yes
pppoptfile = /etc/ppp/options.xl2tpd
length bit = yes

Där alltså ip range betyder vilken range dina devices kommer få addresser i och local ip är vilken address som "vpn-adaptern" på servern kommer att få. Bra att inte sätta den i ranget som devices får ip av kan tilläggas.

Därefter passar vi på att (som vi just konfigurerade) sätta ppp-options i filen /etc/ppp/options.xl2tpd vilket osökt för oss in i nästa steg.

3. Installera/konfigurera PPP
Vi vill förstås ha nått som hanterar användarna, och till det väljer vi PPP.

sudo aptitude install ppp

som vi konfigurerar i ovan nämnda fil /etc/ppp/options.xl2tpd :

require-mschap-v2
ms-dns 8.8.8.8
ms-dns 8.8.4.4
asyncmap 0
auth
crtscts
lock
hide-password
modem
debug
name l2tpd
proxyarp
lcp-echo-interval 30
lcp-echo-failure 4

och eftersom vi nu är på den så kallade "home strech" så passar vi på att lägga till ett lösenord för användaren vi tänkte oss använda när vi loggar in (man har alltså ett username/password och en delad "secret" till nätet, typ som WLAN men bättre). Detta görs med fördel i filen /etc/ppp/chap-secrets :

# user server password ip
test l2tpd testpassword *

och därefter passar vi på att starta om l2tp-demonen :

sudo /etc/init.d/xl2tpd restart

4. Routing, the final frontier.
Nu borde allt vara friden och fröjden, men det är det inte direkt eftersom man inte kommer åt nått utanför intranätet. Detta känns lite tråkigt eftersom hela poängen med vpn för mig är att kunna verka komma hemmifrån. En liten lätt routingförändring i iptables löser biffen :

iptables --table nat --append POSTROUTING --jump MASQUERADE
echo 1 > /proc/sys/net/ipv4/ip_forward

och därefter är du good to go. Ett litet aber är förstås att om man kör debianpaketet för openswan från ubunturepot t.ex. så leker den inte bra nog med xl2tp på grund av versionsförbistringar, så att köra med en OSX-baserad klient funkar obra, men androidtelefoner verkar kirra biffen. Lösningen är enligt uppsago att kompilera en nyare version av openswan men det skiter jag i just nu.

Cheers. Skål och tack för en till.

måndagen den 9:e augusti 2010

Android ListPreference stuff.

Okej, så efter att ha fått nullpointer en hel kväll och tillslut googlat lite så visar det sig att Androids ListPreference inte kan kombinera string-array med integer-array. Inte så smidigt när man vill spara en int med ett namn typ.


Dvs:



<resources>

<string-array name="entries">

<item>En minut</item>

<item>Två minuter</item>

<item>Tre minuter</item>

<item>Tio minuter</item>

</string-array>

<integer-array name="entry_values">

<item>1</item>

<item>2</item>

<item>3</item>

<item>10</item>

</integer-array>

</resources>


fungerar inte, så istället får man göra en



<resources>

<string-array name="entries">

<item>En minut</item>

<item>Två minuter</item>

<item>Tre minuter</item>

<item>Tio minuter</item>

</string-array>

<string-array name="entry_values">

<item>1</item>

<item>2</item>

<item>3</item>

<item>10</item>

</string-array>

</resources>



Kanske kan detta inlägg få mig att slippa jäklas lika länge nästa gång. :P