Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

Wednesday, March 19, 2014

RatingBar madness and solution!

I've been working with Android recently and I just ran into an irritating "quark" with the RatingBar object and I couldn't find a solution through the usual googling and StackExchange, fortunately I stumbled upon a solution!

The Problem:
The ratingBar has a numStars setting which should indicate the maximum number of stars to display for  a rating. In my instance I have this value set to 5, only problem is it displays a many stars and it can possibly fit into the viewable space.. somewhere around 8 stars, uh... hello, I set it to 5!  I love it when things are easy!


This wont do, So here's the code, perfectly reasonable stuff here. (For details on how to do a custom style check out this great blog post, no point in me rewriting this one.)

 <RatingBar
    android:id="@+id/rtbDvcMgmt"
    style="@style/CustomRatingBar"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginRight="25dp"
    android:layout_marginTop="5dp"
    android:max="5"
    android:maxHeight="50dp"
    android:minHeight="28dp"
    android:numStars="5"
    android:rating="0.0"

    android:stepSize="1.0" />

This code has nothing wrong with it, so why is it no working as expected? The explanation can be found in the RatingBar source code java doc! 

When using a RatingBar that supports user interaction, placing widgets to the left or right of the RatingBar is discouraged.
What is meant by "discouraged" is it wont work! All sorts of things go wrong, the stars don't fill properly, there are more stars displayed then you requested... Yes don't do this, it doesn't work.

The cause in my case was that I was using a TextView next to the RatingBar because that's the requirement! I also had the whole form laid out in a Tablerow which doesn't play nicely with RatingBar either as I discovered when I moved the RatingBar onto its own row. 

The Solution!
The solution is surprisingly simple. The RatingBar works when it's all by itself snuggled up in a Layout with nothing to the right or left. so I wrapped it in its own LinearLayout INSIDE of the TableRow with a TextView right next to it! That did the Trick! 



<TableRow
       android:id="@+id/tableRowDvcMgmt"
       android:layout_width="fill_parent"
       android:layout_height="wrap_content"
       android:padding="5sp" >

       <TextView
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           ... />
                
       <LinearLayout
              android:layout_width="fill_parent"
              android:layout_height="wrap_content"
              android:orientation="vertical" >
                       <RatingBar
                           android:id="@+id/rtbDvcMgmt"
                           style="@style/CustomRatingBar"
                           android:layout_width="wrap_content"
                           android:layout_height="wrap_content"
                           android:layout_marginRight="25dp"
                           android:layout_marginTop="5dp"
                           android:max="5"
                           android:maxHeight="50dp"
                           android:minHeight="28dp"
                           android:numStars="5"
                           android:rating="0.0"
                           android:stepSize="1.0" />
       </LinearLayout>
</TableRow>

Tuesday, December 4, 2012

Spring, Autowire and EasyMock

I've been stalling on writing a number of tests I needed because I was caught up on how easily inject a Mock  into a Service that I wanted to test. The problem  was that I didn't want to go to the trouble of cooking up a separate spring context just for tests not to mention I couldn't rely on data in the DB for the DAO to utilize      after all the point of EasyMock is... EASY!  Well that avoiding writing that test that needed a mock finally bit me when some fast refactoring caused something fail because of the lacking test. That's what ya get, right?

After a good deal of hunting I come across a simple solution that I am surprised was so hard to find...

ReflectionTestUtils.setField(serviceYourTesting, "autowireBeanName", yourMock);

That's it! No, really.  OK OK, that's not all you have to do. You are messing with the Service Beans properties so if you have other tests elsewhere that expect that mock object to not be a mock object you'll have to undo what you did.  This isn't such a hassle though. simply call the following and stash that object to restore after you done with the mock.

Object saveBean = ReflectionTestUtils.getField(serviceYourTesting, "autowireBeanName");

I would suggest wrapping your test in a try/finally so you can make sure that the original bean value is set back before the tests concludes. If you don't do this other tests that expect the original bean may fail.

Happy Spring Mocking!

Tuesday, April 26, 2011

Moving to Siena from Play Framework JPA

I Recently built a REST service using the Play Framework and once complete I started looking for a place to deploy the app. Not having a hosted server that runs Java meant I needed a cloud solution and the first to come to mind was GAE. I have used GAE before but this was the first time with Play. (Play and GAE go great together btw.)

Having done little deployment planning from the beginning, it wasnt until a blew through the coding and did a successful deploy that I realized that JPA just doesn't seem to work well with Play's JPA (nothing against Play, GAE just does JPA differently). After a bit of reading that I had skipped past the first time it became evident that I needed to use the Play Siena Module with my GAE app. This turned out to be easier then I though but, I had to hunt around a little to piece together the details so I wanted to share the migration here. This should also be helpful if you are planning to use Siena from the start and already know Play's JPA.

Moving to Siena from the Play JPA was surprisingly simple, I spent more time thinking over weather I wanted to mess with it and looking up the details then actually doing it!

1. Install Siena into Play. (I'm assuming you have Play set up and GAE already installed.)
play install siena-1.5

2. Include in App.conf. Add Siena right under the GAE module like so.

# ---- MODULES ----
module.gae=${play.path}/modules/gae-1.4
module.siena=${play.path}/modules/siena-1.5


3. Change your Models from play.db.jpa.Model to siena.Model. Your just changing an import statement here.

//import play.db.jpa.Model;
import siena.Model;


4. Add an ID field. Play takes care of this for you in the Model but you'll have to add it in for Siena, or make a new Object to inherit from.

  @Id
  public Long id;


5. Update method calls. A few methods have slightly different names but they are pretty obvious and should slow you down.
  1. Model.save() calls become Model.insert()
  2. You'll need to change up your searching, I usually just code methods in the Model to wrap the search queries which means I only have to change the search code in one spot, the Model. Here's a sample of a new search:
  3. Model.all(MonitoredFeed.class).filter("suspended", false).fetch();
  4. Change findAll(), all() calls to Model.All(Your.class) or simply provide a helper method like below.(This could again go in some type of BaseModel reducing your code changes.)
  5. public static Query all() {     return Model.all(MonitoredFeed.class); }
6. Update your Test Fixtures! Of course you have to update the Tests! If your using Fixtures you'll just have to change your imports from Fixture to SienaFixture.

That's all there its to it! Now you can deploy your app on GAE!

Thursday, April 14, 2011

Scripting Groovy to process csv files.

I have a lot of experience with um, "manhandling" flat file data into usable formats. Usually this "data" comes to me in the form of excel spreadsheets, crafted with presentation in mind. They look great but, have little flexibility when it comes to importing the data into relational databases. There are hundreds of solutions for doing this sort of manipulation in bulk and if that's your lot in life by all means beg the IT department to buy you a good data transformation tool!

For some reason my situations are frequently one offs of user data that is begging to get into a database but, as of yet is still running in the wild. My solution has come down to quick Groovy scripts and splicing spreed sheets into multiple CSV files Groovy to chew through. This can be done with Python and many other script languages but, I'm fully fluent in Java so Groovy is my fastest path to a database at this point in time. This is a great place to learn a new scripting language if you have the time but, I usually want this over in a flash. On that note, if you would like to just grab the code and run jump to the bottom to grab My CsvUtils code which takes care of this whole process in a more formal utility object.

Reading a file and working with it is pretty darn simple in Groovy, the following code will open up a CSV and move all the data into nicely structured arrays. (This provides the same results as calling CSVUtils.csvToList())

 //load room types from file
def f= new File('roomtypemap-min.csv');

//set up a List of 'Rows' which will contain a list of 'columns' or you can think of it as array[][]
roomTypes = [];
def lines = 0;
f.splitEachLine(',') {
    def row = [];
    row = it;
    roomTypes << row;
    lines++
}
println "Processed $lines Lines"

The above chewed through a CSV file with name,value pairs of data and placed them in a multi-dimensional array types as a Java list. If your not up on Java collections, it's a whole lot like an array but, better.

Now lets say we did the above code with a few files then process all that data into a new CSV file ready for your code. The code below shows the building of the final results. You'll notice that along with the roomTypes list imported from a CSV file there are now a few others resortList and amenities. All these were pulled from random table dumps and such and I turned them in to usable data.


def aId = 0;    
roomTypes.each{
  def indx = roomTypes.indexOf(it);
  def resortList = roomResortMap[indx];
  def roomType  = it[0];
  
  resortList.each() {
    def facIdx = it.toInteger();
    def facilityId = resorts[it.toInteger()];
    
    amenities.each() {
      def ai = amenities.indexOf(it);
      def avail = values[ai];
      if(avail[facIdx] == true) {
        def description = it;
        println "\"$facilityId\",$roomType,$aId,\"$description\"";
      aId++;
      }
    }
  }

There are a couple things to point out if your new to Groovy. While there is a whole lot of Java in Groovy it also looks a lot like JavaScript making Groovy pretty easy for JavaScript developers to pick up despite deep Java knowledge.

The first thing to note is the iteration I am performing with the .each callback. Personally, I think it looks a good bit like a JavaScript closure. Your simply passing in code to the .each(){} iterator to execute on each item in the List. OH the () is optional when creating this closure so add if you wish.

Second, in the version of Groovy I am using, 1.7.10, you have to do a little bit of work to get the current index position of the for loop. To do this simply call yourListName.indexOf(it). It looks like the upcoming 1.8 is going to have an additional closure called eachWithIndex() which will provide you it and i variables where the i will be the current index. I'm looking forward to that feature!

Finally I just want to point out one of my favorite things for keeping life simple, string replacement. Notice on the next to list line before the braces cascade I'm calling println but, the cool part is the replacements in the string using $fieldName. When your trying to print out complicated strings nothing is worse for readability and bugs then concatenating or calling tons of append() methods. It just leads to errors. You can do simple string replacement with variables using the $fieldName inside your string or for more complicated inserts ${} will work for things like ${Object.field}.

Hope this will help you to simplify the tedious task of data mining text files!

My CSVUtils Object:

/**
 * CSVUtils is released into the public domain, do what ya want with it.
 * By Lee Clarke
 */
public class CSVUtils {  
 
  /**   
   * Removed quotes from around imported csv values if present.
   */
  public static String stripQuotes(String strIn) {  
    def valOut = strIn;  
    if(valOut==null)  
      valOut == "";  
    if(valOut.startsWith("\""))   
      valOut = valOut.substring(1);  
    if(valOut.endsWith("\""))   
      valOut = valOut.substring(0,valOut.length()-1);  
    return valOut;  
  }
    
  /**   
   * Load the csv into a Map using indexed position of values for key and value. 
   * @param keyPos - col index of the key value in a row
   * @param valPos - pull value data from index/col position in row
   * @param csvFilePath - full path to file
   */  
  public static Map csvToMap(int keyPos, int valPos, String csvFilePath) {  
    def fp= new File(csvFilePath);  
    def rtnMap = [:];  
  
    def palines = 0;  
    fp.splitEachLine(',') {  
      if(palines > 0)//skip col header line  
      {  
        def row = [];  
                row = it;  
        def key = CSVUtils.stripQuotes( row[keyPos]);  
        def val = CSVUtils.stripQuotes( (valPos < 0)?row.last():row[valPos]);  
        rtnMap.putAt(key, val);  
      }  
      palines++  
    }  
    return rtnMap;  
  }  
  
  /**
   * loads values in csv file into multi-dimentional like List of rows and cols.
   * @param csvFilePath - full file path.
   * @param skipFirstRow - skip first row if it contains column names.
   */
  public static List csvToList( String csvFilePath, boolean skipFirstRow) {
    def fr= new File(csvFilePath);
    def rtnList = [];
    def rlines = 0;
    fr.splitEachLine(',') {
      if(!(skipFirstRow && rlines == 0)) {
        println "row= $it"
        def row = [];
        row = it;
        rtnList << row;
      }
      rlines++
    }
    return rtnList;
  }
  
  /**
   * loads values in csv file into multi-dimentional like List of rows and cols.
   * @param csvFilePath - full file path.
   */
  public static List csvToList( String csvFilePath) { 
    return csvToList(csvFilePath,true);
  }
}  

Tuesday, February 1, 2011

The Garden Droid 1.0

Well after many months in the lab toiling away with a soldering iron and C compiler I have finally gotten the first version of my Arduino project done! OK really It just took months to get the time to finish the project but that doesn't sound as impressive really.. This is my first Arduino project and first really large electronics project so mistakes were made but overall I'm really happy that it all works!

I really  started the project way back in February of last year and a little over a week ago I planted the GardenDroids first crop, Spinach. I mostly chose spinach because I believe it will grow fairly well in the 75 degree room upstairs where the Droid has been parked as well as its ability to grow in partial sun which I am assuming is about what the LED lighting will produce.. tho I may be mistaking on that. We will see!

So what is a mini-greenhouse? Well in one sentence it's an electronically maintained greenhouse which can be maintained indoors and monitored from your web browser.
This is my mini-greenhouse which I am calling The Garden Droid (you know like garden gnome?)

What you see above is my Garden Droid which boasts a whopping 3 sq. ft. of well lit gardening space, soil moisture monitoring, temperature logging, LED grow lights and wireless transmission of data to my computer. Coming soon it will also be self watering, monitor humidity and ambient light as well as have an upgraded wireless protocol so it can transmit small pictures of the plant growth and support multiple Droids. 
Has I mentioned the website where I can monitor everything going on? Below is a quick snap of the web application which is used to monitor not just the Garden Droid plants but, your whole garden.


The whole project is open source and built on free software with open hardware that anyone can buy and build. I will be trickling out technical details and how to's in the following weeks for anyone interested and heck if my plants grow well I might even sell kits but, first let's see if I can get spinach to grow.

Part of my motivation for this project was to be able to grow salads year round but here in FL most of the summer is not kind to regular spinach and other leafy greens, its just too darn hot and all my efforts have been a failure. I figured that since I am keeping my house artificially cool all summer and the temps would be great for growing greens, why not give it  ago? I plan to eventually get this little box powered by a solar panel collecting dust int he garage as well then there will be a net gain of energy savings though just growing at home saves oil I would think.

Anyway I am really excited about version 1 coming together and I am looking forward to the next version with the enhanced capabilities. To check out the code jump over to my GitHub where you can see the code for the Arduino, the data logging deamon and the full web app.  I will be posting the real technical details just as soon as I can throw together some schematics and I'll keep you posted on the plants progress as well.

Tuesday, May 25, 2010

H2 Database, Junit and Sequence Problems.

Running my Junit tests against a disposable local database has saved me a lot of trouble but, it has given me a couple of problems as well.

I'm quite pleased with how I can bring up a fresh H2 database when I start an JUnit test. I have built a simple JUnit Abstract class which manages the H2 setup loading the DDL for my database followed by sql files that are specific to each unit test (The latter being called from an @BeforeClass method calls a parent method with the path of the unit tests sql inserts. This gives me the ability to seed the database with good test data against which I can run my tests. By doign this I ensure that the data in the database is always exactly what it should be while the test is running. If you have ever tried to run tests against a standing dev database you know it rapidly becomes populated with all sorts of junk from other developers testing or even your own code. With this approach your data is always in a known state, problem solved!

I like H2 and its very useful but,I have come across a couple of oddities using while using it as part of my testing structure. First, while H2 is Oracle compliant if accessed with mode=oracle on the JDBC URL, there are still some DDL and SQL commands which aren't supported, to_date() being a big one.

This is unfortunate since you also want to run your tests against a current database structure and if your in an agile environment with a new database in the works your DB is changing as often as your code! I got around that issue by building a Processor that simply converts all SQL into a compliant format discarding statements that are not usable. Thanks to this processor I can then dump DDL from Toad and simply load up the table export for testing. Nice!

The other notable issue I encountered when implementing this testing framework is encountered when processing the seed data sql. The following simple insert statements creates unexpected SQL errors:

INSERT INTO MY_TABLE (id, some_field, some_other_field) VALUES(MY_TABLE_SEQ.nextval, 'value', 'value');

Note the usage of the sequence call to nextval:  MY_TABLE_SEQ.nextval

For whatever reason this call simply doesn't work. You will receive a SQL error informing you of Primary Key violation requiring a unique id. Yea you SHOULD be inserting one from the sequence but, the H2 sequence is not incremented by the call and you get an old sequence number!

The solution is really quite simple but, sent me on a bit of a hunt trying to figure out what was amiss. In an effort to save someone else a chunk of time here is the solution:

SELECT MY_TABLE_SEQ.nextval from DUAL;
INSERT INTO MY_TABLE (id, some_field, some_other_field) VALUES(MY_TABLE_SEQ.currval, 'value', 'value');


Told you it was simple! I almost feel silly for having spent so much time trying to debug my code! As long as you give H2 a chance to commit a sequence increment, the problem is solved. This works great for testing and solves my problem.

It does imply that there could be issues in H2 if you are doing multiple user inserts and incrementing that sequence so if your in this sort of situation keep your eye out for issues. Fortunately it doesn't effect my local JUnits!