How to use Jython with Spring Boot

What is Jython and why would we need it? Java is a widely preferred language but it‘s not the best choice for every task. As programmers, we should always try to extend our knowledge, learn new languages and try to incorporate them in our day to day work. Python is one of the widely spread […]

by Veselin Davidov

October 23, 2018

4 min read

ai blur codes 577585 scaled 1 - How to use Jython with Spring Boot

What is Jython and why would we need it?

Java is a widely preferred language but it‘s not the best choice for every task. As programmers, we should always try to extend our knowledge, learn new languages and try to incorporate them in our day to day work. Python is one of the widely spread choices for building enterprise applications (maybe even more than Java) and we shouldn’t limit ourselves to only using one of them. There are multiple reasons we might need to integrate some python code in our existing Java application. It can be a library which is already there, an easier yaml processing or just because we like python. Whatever the reason, there is an easy way to achieve that by using Jython – the JVM implementation for the python language. It fully covers the python language and has the pip module manager.

Why Spring boot?

From my experience working in an bespoke development company, Spring is the de facto standard for enterprise applications in the recent years and by using interfaces and dependency injection we can seamlessly integrate our code with the existing java codebase. This way we can get the best out of both worlds and create even better products. In my example I will create a Spring Boot application with a service which is implemented in Jython. Spring Boot provides us with an easy way to get an up and running application in no time. The technique illustrated here is not limited to Spring Boot though. You can use it in a normal Spring application or another framework of choice.

Digging into the code

1.First, we need a simple Spring Boot application.  I used the first one in the Spring tutorial – https://spring.io/guides/gs/spring-boot/

2.Then we need Jython (https://www.jython.org/ ).  I installed version 2.7.1 to my PC and added the dependency to the pom.xml like that:

<dependency>
    <groupId>org.python</groupId>
    <artifactId>jython</artifactId>
    <version>2.7.1</version>
</dependency>

An easier way would be to use jython-standalone artifact here which doesn’t require Jython installation and keeps most of the libraries in the JAR but it has limited functionality and doesn’t allow you to use external modules available through pip.

3.Now we create our interface 

package hello;

public interface HelloService {
	String getHello();	
}

4.And a simple python implementation

from hello import HelloService

class HelloServicePython(HelloService):
    def __init__(self):
        self.value="Hello from python"
       
    def getHello(self):
        return self.value

5.Injecting into the Spring context

Spring cannot create a bean from our python code easily, so we will provide a factory method that creates the object.

package hello;

import org.python.core.Py;
import org.python.core.PyObject;
import org.python.core.PyString;
import org.python.core.PySystemState;
import org.python.util.PythonInterpreter;
import org.springframework.beans.factory.FactoryBean;


public class HelloServiceFactory implements FactoryBean<HelloService> {

 @Override
 public HelloService getObject() throws Exception {
	
	//The python classpath is usually set by environment variable 
//or included in the java project classpath but it can also be set
// programmatically.  Here I hard code it just for the example.
	//This is not required if we use jython standalone JAR 
	PySystemState systemState = Py.getSystemState();
	systemState.path.append(new PyString("C:\jython2.7.1\Lib"));		

	//Here is the actual code that interprets our python file. 
	PythonInterpreter interpreter = new PythonInterpreter();
	interpreter.execfile("python\HelloServicePython.py"); 
	PyObject buildingObject = interpreter.get("HelloServicePython").__call__(); 

//Cast the created object to our Java interface 
	return (HelloService) buildingObject.__tojava__(HelloService.class);  
 }

 @Override
 public Class<?> getObjectType() {
 	return HelloService.class;
 }

}

6.And last step is to start using our Jython implementation in our spring boot application:

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean(name = "helloServiceFactory")
    public HelloServiceFactory helloFactory() {
    	return new HelloServiceFactory();
    }
    
    @Bean(name = "helloServicePython")
    public HelloService helloServicePython() throws Exception {
        return helloFactory().getObject();
    
 
}

And our controller:

@RestController
public class HelloController {

	@Autowired
	@Qualifier("helloServicePython")
	private HelloService service;

	@RequestMapping("/")
	public String index() {
		return service.getHello();
	}

}

7.Result

This is how our project looks in Eclipse and a screenshot of the result:

dreamix, java, python, spring

Conclusion

And that’s all. We can use our python implementation just as we would use a normal Spring service. That was just a simple example but it wouldn’t be much different if we need to create more complex python classes that rely on external libraries, etc. We can also extend Java classes in Python. It’s a powerful tool which can find many uses and advance our products to the next level!