- Small (3-5 person team)
- Profitable (will charge users in exchange for great products)
- Bootstrapped (no outside funding)
-
Pages
-
Categories
-
Archives
I attended the Saas Entreprenuer Camp last December 3 and 4 at Davao, Philippines. Winston Damarillo gave a mentor talk about starting tech businesses. According to Winston, your idea is a potential business and not just a “project” if:
1. You can articulate how to make money
I very much agree with this. One of the main reasons why I’m doing startups is the chance to create wealth and life-changing money. This can’t happen if my idea doesn’t have a business model.
2. You can describe your competitors
If your idea is the only one out there, it could mean two things. First, you’ve really created something new and innovative. Second, there isn’t any market for your idea or there isn’t any way to make money. Most of the time it’s the second reason. If there’s already a market for your idea, knowing your competitors would also help you determine where to position yourself. For example, you can position yourself to be the “simplest to use” or “cheapest in terms of price”.
3. You put your own money into it
You should be willing to invest your own money into the idea. This will also make investors confident to give you money. You’ll also take your idea more seriously if you’ve invested your own money into it. “Money” doesn’t necessarily have to be cash. If you still have a day job, you could invest your time to the idea. You can work on your idea instead of taking vacations. No more leisure time. Attending business and startup conferences at your own expense is also a way of investing to your idea.
To recap, your idea is a potential business and not just a “project” if:
1. You can articulate how to make money
2. You can describe your competitors
3. You put your own money into it
I’m giving up the domain MicroISV.ph. This blog is now at http://blog.milobjects.com.
I developed an Android application called Rescue Me. It’s my entry for the Smart Mobile Developer Competition. Please help me win by voting for “milObjects Software” at http://vote.smartvasnet.com/mobdev/.
Here’s a video of the app.
Here’s a PDF info sheet of the app. Download the app here if you’d like to try it on an emulator or actual phone. Thanks!
I created a custom tag to handle i18n in text images. It’s a simple tag and basically a hack of createLinkTo tag. I named it createLinkToImage. I’m trying to add this to http://www.grails.org/Contribute+a+Tag but I just get a blank page when I click save (after logging in and editing the page).
createLinkToImage Tag
For applying i18n to your text images. Text images are images with text. For example, your default (English) send.gif button image says “Send”. You want to translate this to Japanese for your Japanese users. You put send.gif (English) in /images directory and put send.gif (Japanese) in /images/ja directory. Both should have the same filename. In messages.properties, put an entry “images.dir=images” (without quotes). In messages_ja.properties, put an entry “images.dir=images/ja” (without quotes).
<input type=”image” value=”Send” src=”${createLinkToImage(dir:’images.dir’,file:’send.gif’)}”/>
def createLinkToImage = { attrs ->
attrs.dir = message(code: attrs.dir, default: 'images')
out << g.resource(attrs)
}
I’m always looking for ways to make SignApp Now faster. A colleague, Butch Landingin, informed me of this Grails plugin that might help. I’m installing it now. I’ll post how it goes later.
I’ve recently released our first webapp/product. As mentioned in a previous post, the webapp is running on Jetty (plus Apache and MySQL). People who initially used the webapp complained of it being slow. It worried me because I thought I had to increase the server’s memory or I had to deploy it to a hosted platform like Google AppEngine. I didn’t want to increase the server’s memory because it would mean my monthly VPS fee would increase. I’m trying to keep expenses at a minimum until the webapp is earning income. The webapp is free by the way. I didn’t want to deploy it to Google AppEngine because I’d have to rewrite the code. I used Grails by the way. So my only option was to optimize/reconfigure either Apache, Jetty, MySQL, or all of them. I decided to optimized Jetty first because it’s where the webapp is deployed. After googling “Jetty Optimization” I found these sites: http://jetty.mortbay.org/jetty5/doc/optimization.html and http://docs.codehaus.org/display/JETTY/Jetty+Documentation. You can read through these links and apply the steps in there. But if you’re in a hurry and want to read a summary, here’s what I did:
cache-control headers in the response (http://docs.codehaus.org/display/JETTY/LastModifiedCacheControl). This tells the browser to cache static content (images, CSS, Javascripts, etc.) so it won’t have to be requested every time a page is accessed. I did this by modifying $JETTY_HOME/etc/webdefault.xml. Make sure this servlet init parameter is not commented out (this is under the DefaultServlet’s declaration):
<init-param>
<param-name>cacheControl</param-name>
<param-value>max-age=3600,public</param-value>
</init-param>
webdefault.xml again and look for the JspServlet declaration. Follow the steps in http://docs.codehaus.org/display/JETTY/Jsp+Configuration to set development mode to false and disable JSP runtime recompilation.RequestLog was disabled as mentioned in http://jetty.mortbay.org/jetty5/doc/optimization.html (look for “Optimizing Jetty > Request Log Buffering”)The things I did above made the webapp faster. But I’m not sure if it would remain fast as users increase. But I’ll worry about that later. I think a slow webapp due to an increase in usage is a good thing. But making it fast again is very important.
This is how I configured Apache and Jetty to host my two webapps. Each webapp was deployed to their own root domains. It took me about a week of trials and errors to get this to work.
Background
I have two webapps that I’d like to deploy on my Rimuhosting VPS. The first webapp is a Grails app and will be deployed to www.signappnow.com. The second webapp is an AppFuse app and will be deployed to www.mybooks.ph. I have the following installed:
Apache Server 2.2.3
Jetty 6.1.18
Step 1 – Deploy the webapps to Jetty
I deployed the first webapp to port 8080 and the second to port 8081. I’ll explain later why I did this. I followed the instructions here.
I configured two servers. The first with port 8080 and the second with port 8081. The default Jetty configuration file at $JETTY_HOME/etc/jetty.xml is already configured to run on port 8080. I copied jetty.xml to $JETTY_HOME/etc/jetty-Server2.xml. jetty-Server2.xml is the second server. I modified the following on jetty-Server2.xml:
- I changed the server id.
<Configure id="Server2" class="org.mortbay.jetty.Server">
- I changed the default port.
<Call name="addConnector">
<Arg>
<New class="org.mortbay.jetty.nio.SelectChannelConnector">
<Set name="host"><SystemProperty name="jetty.host" /></Set>
<Set name="port"><SystemProperty name="jetty.port" default="8081"/></Set>
<Set name="maxIdleTime">30000</Set>
<Set name="Acceptors">2</Set>
<Set name="statsOn">false</Set>
<Set name="confidentialPort">8443</Set>
<Set name="lowResourcesConnections">5000</Set>
<Set name="lowResourcesMaxIdleTime">5000</Set>
</New>
</Arg>
</Call>
- I changed the default context directory so webapp contexts I put in the directory will not be picked up by the default server.
<Call name="addLifeCycle">
<Arg>
<New class="org.mortbay.jetty.deployer.ContextDeployer">
<Set name="contexts"><Ref id="Contexts"/></Set>
<Set name="configurationDir"><SystemProperty name="jetty.home" default="."/>/contexts/Server2</Set>
<Set name="scanInterval">5</Set>
</New>
</Arg>
</Call>
- I commented out the WebAppDeployer because I don’t plan to deploy webapps this way. If you want to deploy webapps this way, configure it to use another webapps directory so it will be different from the default server.
<!--
<Call name="addLifeCycle">
<Arg>
<New class="org.mortbay.jetty.deployer.WebAppDeployer">
<Set name="contexts"><Ref id="Contexts"/></Set>
<Set name="webAppDir"><SystemProperty name="jetty.home" default="."/>/webapps</Set>
<Set name="parentLoaderPriority">false</Set>
<Set name="extract">true</Set>
<Set name="allowDuplicates">false</Set>
<Set name="defaultsDescriptor"><SystemProperty name="jetty.home" default="."/>/etc/webdefault.xml</Set>
</New>
</Arg>
</Call>
-->
I created context files for each of the webapps: $JETTY_HOME/contexts/signapp.xml and $JETTY_HOME/contexts/Server2/mybooks.xml. I used $JETTY_HOME/contexts/test.xml as a template.
signapp.xml:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
<Configure class="org.mortbay.jetty.webapp.WebAppContext">
<Set name="contextPath">/</Set>
<Set name="war">/projects/webapps/signapp/signapp-0.1.war</Set>
<!-- virtual hosts -->
<Set name="virtualHosts">
<Array type="String">
<Item>www.signappnow.com</Item>
<Item>signappnow.com</Item>
</Array>
</Set>
</Configure>
mybooks.xml:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
<Configure class="org.mortbay.jetty.webapp.WebAppContext">
<Set name="contextPath">/</Set>
<Set name="war">/projects/webapps/mybooks/mybooks-1.0.war</Set>
<!-- virtual hosts -->
<Set name="virtualHosts">
<Array type="String">
<Item>www.mybooks.ph</Item>
<Item>mybooks.ph</Item>
</Array>
</Set>
</Configure>
You can read more about Jetty Virtual Hosts here http://docs.codehaus.org/display/JETTY/Virtual+hosts.
I went to $JETTY_HOME/ and started Jetty, passing the two configuration files:
./bin/jetty.sh jetty.xml jetty-Server2.xml
I accessed my webapps at http://signappnow:8080/ and http://mybooks.ph:8081/. They’re up!
Step 2 – Configure Apache
I already have Apache running on port 80 and it’s serving other sites. That’s why I couldn’t use port 80 on Jetty. But I still needed my webapps to be accessible on port 80.
I created the folowing .conf files in Apache:
$APACHE_HOME/conf.d/signapp.conf
<VirtualHost *:80>
ServerName signappnow.com
ServerAlias www.signappnow.com
ProxyRequests Off
ProxyPreserveHost On
ProxyPass / http://localhost:8080/
ProxyPassReverse / http://localhost:8080/
</VirtualHost>
$APACHE_HOME/conf.d/mybooks.conf
<VirtualHost *:80>
ServerName mybooks.ph
ServerAlias www.mybooks.ph
ProxyRequests Off
ProxyPreserveHost On
ProxyPass / http://localhost:8081/
ProxyPassReverse / http://localhost:8081/
</VirtualHost>
Make sure the needed Apache mod_proxy modules are loaded when Apache is started. I restarted Apache after adding the .conf files:
/etc/init.d/httpd restart
I accessed http://signappnow.com and http://mybooks.ph to see if they worked. They did!
Basically, Apache will forward all requests to signappnow.com to http://localhost:8080/, which is the first Jetty Server. Jetty will figure out that it’s for the first webapp because of the configured VirtualHosts. This is also what happens to requests to mybooks.ph
Why did I configure two Jetty servers?
I initially deployed my webapps on one Jetty server on port 8080. But I encountered a problem with my Grails webapp. When I start Jetty, both webapps are successfully loaded according to the log file. The AppFuse webapp works. The Grails app on the other hand only serves blank pages. There are no errors in the log file. If I undeploy the AppFuse webapp, the Grails webapp works. I think it has something to do with both of them having the same root context path “/”. I haven’t really found out why it behaves this way. This only happens with my Grails webapp. I tried another webapp and it worked. So the only solution I thought of was deploying them on separate servers with different ports.
Lastly, if you encounter Java out of memory or permgen errors, just pass -Xms, -Xmx, and -XX:MaxPermSize to Jetty when it starts. I did it by create the file /etc/default/jetty. This file contains:
JAVA_OPTIONS="-server -Xms16m -Xmx128m -XX:MaxPermSize=128m -Djava.awt.headless=true"
Welcome to WordPress. This is your first post. Edit or delete it, then start blogging!