Wednesday, September 5, 2018

Teach My Kids Python - How to create web service using Flask

Python is the language that helps you put together your idea faster than most other computer languages.  Micro-controller like Raspberry Pi also let you write in Python to control electronic
device such as robots, yes, robots...



Before getting to build a robot, this blog is to teach you how to build a simple web service using Python.  To begin, let starts with a well known Python language editor (the computer language editor is referred as "Integrated Development Environment, IDE in short).    The Python IDE can be downloaded from the following link.

Getting PyCharm

Once the IDE is installed, you can open the IDE.  The program you are going to write is to serve a  text in JSON format when an user open a link using web browser to your web service.

A JSON message have the following format:

{
    "glossary": {
        "title": "example glossary",
  "GlossDiv": {
            "title": "S",
   "GlossList": {
                "GlossEntry": {
                    "ID": "SGML",
     "SortAs": "SGML",
     "GlossTerm": "Standard Generalized Markup Language",
     "Acronym": "SGML",
     "Abbrev": "ISO 8879:1986",
     "GlossDef": {
                        "para": "A meta-markup language, used to create markup languages such as DocBook.",
      "GlossSeeAlso": ["GML", "XML"]
                    },
     "GlossSee": "markup"
                }
            }
        }
    }
}

JSON messages are widely exchanged between computer systems.  In this blog, you will also 
learn how to read JSON message from a text file stored in your computer.



Section 1


Create a Python project, name it "mocked_analytic_server", click the Create button 
when you are done.
 






Section 2


Create a requirements.txt file to specify the Flask library for your web service program.  
The flask library information can be found at this link: PyPI libraries. PyPI is the 
place where you find all kinds of libraries included controlling robots.






















Once you created requirements.txt, enter the following flask library you needed:
flask==1.0.2
At the time of this writing 1.0.2 is the latest version for the Flask library.
















The IDE should offer you to install the library.  So, please click on "Install requirement".
When it is done, you will see the following pop-up:











Section 3


Now create a new file again, this time named it as "sample.json", and enter any JSON 
you like.  For example:

{
 "age":1000,
 "name":"Dark Vader",
 "messages":["Luke", "I am your father"]
}

The correct format of the JSON message is important, so if you cannot type well, just copy
above example JSON text to sample.json.















Below screenshot is just an example, the JSON you entered can be different
from the screenshot:

































Section 4


On the the main program, create a Python file, name it "main.py":





















Then you have to type the following Python code.  Sorry, no copying this time.. You have 
to learn from mistakes:






















Section 5


It is the test to try out your program by running it. Right click on main.py on the
left panel, it will have a pop up:































Click on Run 'main', and you will see your web service is running on the lower panel:


















Then, click on the link http://127.0.0.1:5000.  It will launch your web browser, and
show the JSON message:










Your JSON message can be different from mine.

Section 6


To show it off to your friend, either 

1. Tell your friend to come to your home to look.
2. Ask your dad to configure your router, set port forward to your running
   web service running on port 5000

Number 2 is not recommended because there are tons of hackers out there looking
for opportunity to take over your computer.

Monday, June 15, 2009

Secured Web Service Using Spring Security

At work, I came across a problem of adding basic HTTP authentication to web service. The following configuration for Spring security would work:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:s="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
classpath:/schemas/spring-beans-2.5.xsd
http://www.springframework.org/schema/security
classpath:/schemas/spring-security-2.5.xsd">

<s:http auto-config="false">
<s:form-login />
<s:anonymous />
<s:http-basic />
<s:logout />


<!-- List of web services to intercept for security check -->

<s:intercept-url pattern="/services/OrderService"
method="POST" access="ROLE_APPL_ORDER_SYSTEM" />

<!--
Essentially no security for all other URLs since everything is
granted to Anonymous
-->
<s:intercept-url pattern="/**"
access="IS_AUTHENTICATED_ANONYMOUSLY" />

</s:http>


<!-- LDAP authentication provider configuration -->
<s:ldap-server url="ldap://ldap.myserver.org:389" />
<s:ldap-authentication-provider
user-search-base="OU=People,O=javaidiot.org" user-search-filter="uid={0}"
group-search-base="OU=Groups,O=javaidiot.org" group-search-filter="uniquemember={0}"
group-role-attribute="CN" />

</beans>

Note: Authentication and Authorization is being done above, the user account has to be existed in the LDAP server with the role APPL_ORDER_SYSTEM. In the configuration, pay attention to the "ROLE_" prepended to the actual role because I think it is the convention required.

In your Web Service client, you can do this:

((BindingProvider) port).getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "username");
((BindingProvider) port).getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "password");

Here is the remaining context setup for Spring webservice:

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ws="http://jax-ws.dev.java.net/spring/core"
xmlns:wss="http://jax-ws.dev.java.net/spring/servlet"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
classpath:/schemas/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop
classpath:/schemas/spring-aop-2.5.xsd
http://jax-ws.dev.java.net/spring/core
classpath:/schemas/core.xsd
http://jax-ws.dev.java.net/spring/servlet
classpath:/schemas/servlet.xsd">

<!-- OrderService -->
<wss:binding url="/services/OrderService">
<wss:service>
<ws:service bean="#orderServiceImpl">
</ws:service>
</wss:service>
</wss:binding>

<bean id="orderServiceImpl"
class="org.javaidiot.impl.OrderServiceImpl" />

</beans>

Here is the web.xml:

<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
<display-name>Archetype Created Web Application</display-name>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<servlet>
<servlet-name>dispatch</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>


<!-- OrderService -->
<servlet>
<servlet-name>OrderService</servlet-name>
<display-name>OrderService</display-name>
<description>Order Service</description>
<servlet-class>com.sun.xml.ws.transport.http.servlet.WSSpringServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>OrderService</servlet-name>
<url-pattern>/services/OrderService</url-pattern>
</servlet-mapping>

<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>

</web-app>


To enable SSL on Tomcat, you will need a key-pairs. You can either buy, get, or use Java keytool to get a self-generated one. Then go to the server.xml to adapt the following line:

<Connector SSLEnabled="true" clientAuth="false" keystoreFile="C:/my_identity.jks"
keystorePass="changeit" maxThreads="150" port="8443" protocol="HTTP/1.1" scheme="https" secure="true"
sslProtocol="TLS" truststoreFile="C:/my_client_trust_to_other_server.jks" truststorePass="changeit"/>

Notice your webservice client now will need the following VM arguments to start:

-Djavax.net.ssl.trustStore="C:\my_client_trust.jks"
-Djavax.net.ssl.trustStorePassword=changeit

Friday, June 12, 2009

A Custom Distributed Lock for Spring Application

I will try to demonstrate how two Spring's applications that can share the same lock.

For example:

When Application 1 and 2 call the method lock("mycheese", 20000L), one of the applications will be able to get the lock, the other will not. The example lock would expire in 20000 milliseconds or can be removed earlier by calling the method unlock("mycheese").

To begin, I will show the Application 1 & 2 contexts:

file: context1.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


<bean id="contextApplicationContextProvider" class="org.javaidot.lock.ApplicationContextProvider"></bean>

<bean id="lockManager" class="org.javaidot.lock.LockManager">
<property name="memberId" value="1" />
</bean>

<bean id="scheduledTask" class="org.springframework.scheduling.timer.ScheduledTimerTask">
<!-- wait 1 seconds before starting repeated execution -->
<property name="delay" value="1000"/>
<!-- run every 2 seconds -->
<property name="period" value="2000"/>
<property name="timerTask" ref="lockManager"/>
</bean>

<bean id="timeFactory" class="org.springframework.scheduling.timer.TimerFactoryBean">
<property name="scheduledTimerTasks">
<list>
<ref bean="scheduledTask"/>
</list>
</property>
<property name="daemon" value="false"/>
</bean>

<bean id="lockServiceImpl" class="org.javaidot.lock.LockServiceImpl"/>

<bean class="org.springframework.remoting.rmi.RmiServiceExporter">
<property name="serviceName" value="LockService"/>
<property name="service" ref="lockServiceImpl"/>
<property name="serviceInterface" value="org.javaidot.lock.LockService"/>
<property name="registryPort" value="1236"/>
</bean>

<bean id="remoteLockServiceImpl" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<property name="serviceUrl" value="rmi://localhost:1235/LockService"/>
<property name="serviceInterface" value="org.javaidot.lock.LockService"/>
<property name="refreshStubOnConnectFailure" value="true"/>
<property name="lookupStubOnStartup" value="false"/>
<!-- <property name="cacheStub" value="true"/>-->
</bean>
</beans>



file: context2.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


<bean id="contextApplicationContextProvider" class="org.javaidot.lock.ApplicationContextProvider"></bean>

<bean id="lockManager" class="org.javaidot.lock.LockManager">
<property name="memberId" value="2" />
</bean>

<bean id="scheduledTask" class="org.springframework.scheduling.timer.ScheduledTimerTask">
<!-- wait 1 seconds before starting repeated execution -->
<property name="delay" value="1000"/>
<!-- property name="fixedRate" value="true"/-->
<!-- run every 2 seconds -->
<property name="period" value="2000"/>
<property name="timerTask" ref="lockManager"/>
</bean>

<bean id="timeFactory" class="org.springframework.scheduling.timer.TimerFactoryBean">
<property name="scheduledTimerTasks">
<list>
<ref bean="scheduledTask"/>
</list>
</property>
<property name="daemon" value="false"/>
</bean>

<bean id="lockServiceImpl" class="org.javaidot.lock.LockServiceImpl"/>

<bean class="org.springframework.remoting.rmi.RmiServiceExporter">
<property name="serviceName" value="LockService"/>
<property name="service" ref="lockServiceImpl"/>
<property name="serviceInterface" value="org.javaidot.lock.LockService"/>
<property name="registryPort" value="1235"/>
</bean>

<bean id="remoteLockServiceImpl" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<property name="serviceUrl" value="rmi://localhost:1236/LockService"/>
<property name="serviceInterface" value="org.javaidot.lock.LockService"/>
<property name="refreshStubOnConnectFailure" value="true"/>
<property name="lookupStubOnStartup" value="false"/>
<!-- <property name="cacheStub" value="true"/>-->
</bean>

</beans>


The summary for the contexts above:
  1. ApplicationContextProvider implements Spring's ApplicationConextAware to hold the ApplicationContext. The purpose to hold the original spring context. All the credits here goes to the author Siegried Bolz.
  2. LockManager hold a dictionary of locks to be managed, it also implements Java TimerTask.
  3. ScheduledTimerTask is used to kick of the run method in LockManager to clean up expired locks.
  4. LockServiceImpl implement the lock and unlock method for RMI client.
  5. RmiServiceExporter is the RMI Server for RMI Client
  6. RmiProxyFactoryBean is the RMI client to the other application RMI Server.


Below are the source listings of the entire application, the Main1.java and Main2.java are the test classes:


file: AppContext.java


package org.javaidiot.lock;

import org.springframework.context.ApplicationContext;

/**
* This class provides application-wide access to the Spring ApplicationContext.
* The ApplicationContext is injected by the class "ApplicationContextProvider".
*
* @author Siegfried Bolz
*/

public class AppContext {

private static ApplicationContext ctx;

/**
* Injected from the class "ApplicationContextProvider" which is automatically
* loaded during Spring-Initialization.
*/

public static void setApplicationContext(ApplicationContext applicationContext) {
ctx = applicationContext;
}

/**
* Get access to the Spring ApplicationContext from everywhere in your Application.
*
* @return
*/

public static ApplicationContext getApplicationContext() {
return ctx;
}
}



file: ApplicationContextProvider.java


package org.javaidiot.lock;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
/**
* This class provides an application-wide access to the
* Spring ApplicationContext! The ApplicationContext is
* injected in a static method of the class "AppContext".
*
* Use AppContext.getApplicationContext() to get access
* to all Spring Beans.
*
* @author Siegfried Bolz
*/
public class ApplicationContextProvider implements ApplicationContextAware {

public void setApplicationContext(ApplicationContext ctx) throws BeansException {
// Wiring the ApplicationContext into a static method
AppContext.setApplicationContext(ctx);
}
}



file: ILock.java

package org.javaidiot.lock;

public interface ILock {

public abstract String getName();

public abstract void setName(String name);

public abstract Long getExpirationInMs();

public abstract void setExpirationInMs(Long expirationInMs);

public abstract Long getLockTimeInMs();

public abstract void setLockTimeInMs(Long lockTimeInMs);

public abstract Long getRequesterId();

public abstract void setRequesterId(Long requesterId);

}


file: Lock.java


package org.javaidiot.lock;

import java.io.Serializable;

public class Lock implements Serializable, ILock {


private static final long serialVersionUID = 6437744860401621455L;

private String name;
private Long expirationInMs;
private Long lockTimeInMs;
private Long requesterId;

public Lock(String name, Long expirationInMs, Long memberId) {
super();
this.name = name;
this.expirationInMs = expirationInMs;
this.requesterId = memberId;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Long getExpirationInMs() {
return expirationInMs;
}

public void setExpirationInMs(Long expirationInMs) {
this.expirationInMs = expirationInMs;
}

public Long getLockTimeInMs() {
return lockTimeInMs;
}

public void setLockTimeInMs(Long lockTimeInMs) {
this.lockTimeInMs = lockTimeInMs;
}

public Long getRequesterId() {
return requesterId;
}

public void setRequesterId(Long requesterId) {
this.requesterId = requesterId;
}

public String toString() {
return "name=" this.name
", lockTimeInMs=" this.lockTimeInMs
", expirationInMs=" this.expirationInMs
", requesterId=" this.requesterId;
}

}

file: LockManager.java


package org.javaidiot.lock;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TimerTask;
import org.springframework.context.ApplicationContext;

public class LockManager extends TimerTask {

private ApplicationContext ctx;
private Long memberId;
private Map <String, Lock> locks = new HashMap <String, Lock> ();

public LockManager() {
ctx = AppContext.getApplicationContext();
}

public Long getMemberId() {
return memberId;
}

public void setMemberId(Long memberId) {
this.memberId = memberId;
}

public boolean lock(String name, Long timeToLiveInMs) {

Boolean bool = false;

Long expirationInMs = timeToLiveInMs System.currentTimeMillis();

Lock lock = new Lock(name, expirationInMs, memberId);

boolean localBool = createLockLocally(lock);

System.out.println("localBool:" localBool);


boolean remoteBool = false;

try {
remoteBool = createLockRemotely(lock);
System.out.println("remoteBool:" remoteBool);
} catch (RuntimeException e) {
System.out.println("Remote Lock service is down??");
}

if ((localBool == true) && (remoteBool == true)) {
bool = true;
}

return bool;
}

public void unlock(String name) {

ILock lock = locks.get(name);

removeLockLocally(lock);

try {
removeLockRemotely(lock);
} catch (Exception e) {
System.out.println("remote lock service is down!");
}
}

public void showLocks() {

System.out.println("\nList of Locks:");
System.out.println("------------------");
Set <String> keys = locks.keySet();
for (String key: keys) {
System.out.println(locks.get(key));
}
}

public boolean createLockRemotely(Lock lock) {
System.out.println("creating lock remotely");

LockService lockService = (LockService) ctx.getBean("remoteLockServiceImpl");
return lockService.createLock(lock);
}

public boolean createLockLocally(Lock lock) {
System.out.println("creating lock locally");

if (locks.containsKey(lock.getName())) {
return false;
}
locks.put(lock.getName(), lock);
System.out.println("created lock locally: " lock);
return true;
}

public void removeLockLocally(ILock lock) {
System.out.println("removing lock locally");

locks.remove(lock.getName());
System.out.println("removed lock locally: " lock.getName());
}

public void removeLockRemotely(ILock lock) {
System.out.println("removing lock remotely");

LockService lockService = (LockService) ctx.getBean("remoteLockServiceImpl");
lockService.removeLock(lock);
}

@Override
public void run() {

showLocks();

Set <String> keys = locks.keySet();
for (String key: keys) {
ILock lock = locks.get(key);
if (System.currentTimeMillis() > lock.getExpirationInMs())
locks.remove(key);
}
}

public Map<String, Lock> getLocks() {
return locks;
}

public void setLocks(Map<String, Lock> locks) {
this.locks = locks;
}

}

file: LockService.java


package org.javaidiot.lock;

public interface LockService {
public boolean createLock(Lock lock);
public void removeLock(ILock lock);
}

file: LockServiceImpl.java


package org.javaidiot.lock;


import org.springframework.context.ApplicationContext;

public class LockServiceImpl implements LockService {

private ApplicationContext ctx;

public LockServiceImpl() {
ctx = AppContext.getApplicationContext();
}
@Override
public boolean createLock(Lock lock) {

boolean ret = false;
LockManager lockManager = (LockManager) ctx.getBean("lockManager");

Long memberId = lockManager.getMemberId();

System.out.println("Processing createLock from requester " lock.getRequesterId());
if (memberId != lock.getRequesterId()) {
ret = lockManager.createLockLocally(lock);
}
return ret;
}
@Override
public void removeLock(ILock lock) {

LockManager lockManager = (LockManager) ctx.getBean("lockManager");
Long memberId = lockManager.getMemberId();

System.out.println("Processing removeLock from requester " lock.getRequesterId());
if (memberId != lock.getRequesterId()) {
lockManager.removeLockLocally(lock);
}
}
}

file: Main1.java


package org.javaidiot.lock;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main1 {

public static void main(String[] args) throws Exception {

ApplicationContext ctx = new ClassPathXmlApplicationContext("context1.xml");

LockManager lockManager = (LockManager) ctx.getBean("lockManager");

boolean bool = lockManager.lock("mycheese", 40000L);

System.out.println("Main1: locked:" bool);

bool = lockManager.lock("mycheese", 40000L);
System.out.println("Main1: locked:" bool);

Thread.sleep(10000);

lockManager.unlock("mycheese");
}
}

file: Main1.java


package org.javaidiot.lock;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main2 {

public static void main(String[] args) throws Exception {

ApplicationContext ctx = new ClassPathXmlApplicationContext("context2.xml");

LockManager lockManager = (LockManager) ctx.getBean("lockManager");

Thread.sleep(20000);

System.out.println("Main2: getLock:" lockManager.lock("mycheese", 20000L));
}

}