2. Small Intro
● Marco Pas (1973)
› Education in Chemistry and then
moved to Transportation & Logistics
to finally IT.. what is next?
● Software Engineer
● Burgundian lifestyle
Wikipedia tells us :
'enjoyment of life, good food,and extravagant spectacle'
3. Agenda
● What the heck am I trying to solve!!
● How on earth did we solve it?
● What are our plans for the future?
6. Convention Fueling != Electric Vehicle Charging
● EV Charging Challenges:
› Impossible to store & forward electricity
› Charge often (Limited Range)
› Time to charge (from minutes to hours)
› Compatibility (plugs, charging cables)
10. Charging Process
Back OfficeValidation / Verification
● Is the card valid?
● Electricity pricing?
● How much can I charge?
● Who is the customer?
● Did you make a reservation?
● ….
12. How to manage
all those
(different kind of)
Chargers?
Stakeholders?
Processes?
13. Requirements
● Implement a platform that enables EV Infra management:
› To monitor a Charge Point (CP) network
› Supports remote management
› Track charging sessions
● Including charge authorization &
transaction storage
› Multi-tenancy
› 3rd
party integration using Web Services (SOAP / REST)
16. Open Charge Point Protocol (OCPP)
● Open protocol between charging stations and a managing central
system aka back office
› Asynchronous
› Based on SOAP (v1.2)
› Working group with support from all manufacturers!
17. Agenda
● What the heck am I trying to solve!!
● How on earth did we solve it?
● What are our plans for the future?
18. Release 1.0
!
! SOAP ~ Contract First with Grails was not that easy, so we moved to a pure JAVA/Spring OCPP application
19. Jackson JSON Mapper
public class JsonMapper extends ObjectMapper {
public JsonMapper() {
super();
/**
* De-Serialization options JSON -> OBJECT
*/
// - ignore unknown fields - otherwise the construction of the object will fail!
this.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// - make it possible to also construct empty objects
this.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
/**
* Serialization options OBJECT -> JSON
*/
// properties with non-null values are to be included in the resulting JSON
this.setSerializationInclusion(JsonInclude.Include.NON_NULL);
}
}
20. Jackson JSON Mapper
● JSON → Object
● Object → JSON
resources.groovy
beans = {
// a preconfigured Jackson JSON mapper with defaults
jsonMapper(JsonMapper){}
}
def jsonContent = “{'name': 'John Doe'}”
Person person = jsonMapper.readValue(jsonContent, Person.class)
Person person = new Person(name: 'John Doe')
def jsonContent = jsonMapper.valueToTree(person)
21. Theming support
● Login-Logout & user configurable themes
● Using Spring Security Core Plugin
Config.groovy
// make sure we can act on security events
grails.plugins.springsecurity.useSecurityEventListener = true
// executed when a user succesfully authenticates into the application
grails.plugins.springsecurity.onInteractiveAuthenticationSuccessEvent = { e, appCtx →
// .. code intentionally emitted .. //
session.theme = “MyNameOfTheTheme”
}
page.gsp
<g:if test="${session?.theme == null}">
<% session.theme="${grailsApplication.config.default.theme}"%>
</g:if>
<r:require module="${session?.theme}"/>
<g:external uri="/css/themes/${session?.theme - "theme_"}/images/favicon.ico"/>
25. Technical Debt
● Client was very happy but.... shame on us:
› Tightly coupled
› Poor test coverage
› Spring project & Grails project
› Adding functional value is just to much fun!
● But... ready for round 2..
› Thanks to Grails we could refactor with great ease and speed!
26. Release 2.0
● Guidelines:
› Focus on creating a modular platform
› Test Driven Development
› Use Grails for everything!!
› Minimize the use of plugins!!!
27. Grails CXF Plugin
● WSDL
› Contract First & Code First
● Wire Interceptors
› Logging, Security
● Support for versioning
@GrailsCxfEndpoint(address='/myCustomSoapService/v2/')
28. Annotated example
@GrailsCxfEndpoint(
address='/centralsystem/ocpp/v1/5',
wsdl = 'wsdl/ocpp_15_centralsystem.wsdl',
expose = EndpointType.JAX_WS_WSDL,
soap12 = true,
inInterceptors = ["logSoapInboundInterceptor", "setReplyToSOAPHeaderInInterceptor"],
outInterceptors = ["logSoapOutboundInterceptor"])
@WebService(
name = "CentralSystemService",
targetNamespace = "urn://Ocpp/Cs/2012/06/",
serviceName = "CentralSystemService",
portName = "CentralSystemServiceSoap12"
)
@GZIP
class CentralSystemOcpp15Service implements CentralSystemService {
// ... code intentionally omitted
// ... contains the methods that needs to be implemented due to the 'implements'
}
29. Demo
● Create a contract first webservice using Grails CXF plugin
› Source WSDL: CustomerService.wsdl
› Steps:
● Create grails project
● Install CXF plugin
● Use WSDL2JAVA to generate web service implementation
● Create Grails service that implements the web service interface
● Test using SOAPUI
31. RabbitMQ – an AMQP implementation
● Grails RabbitMQ Plugin
› High-level abstraction for sending and receiving messages
› Fallback to Spring Template
class MessageReceiveService {
static rabbitQueue = 'helloQ'
void handleMessage(message) {
// handle message…
}
}
class MessageSendController {
def sendMessage = {
rabbitSend 'helloQ', 'Hello!'
}
}
32. RabbitMQ Synchronous
class MessageSendController {
def rabbitTemplate // use the Spring rabbitTemplate directly
def sendMessage = {
def response = rabbitTemplate.convertSendAndReceive 'helloQ', 'Hello World'
println response
}
}
class MessageReceiveService {
static rabbitQueue = [queues: 'helloQ', messageConverterBean: '']
void handleMessage(Message message) {
// determine the reply queue
def returnQueue = message.messageProperties.replyTo
// return the response to temporary return queue..
rabbitSend returnQueue, 'Hello there'
}
}
33. Demo
● Send and Consume a message via RabbitMQ
› Steps:
● Install RabbitMQ plugin
● Configure Grails app to use RabbitMQ
● Create code to publish and consume a message
40. WebSockets
● Defines an API establishing a "socket" connections between a
client and a server
› Providing full-duplex communication
channel over a single TCP
connection
› HTTP upgrade by
Protocol Negotiation
› Firewall friendly! (port 80)
› No reconnect handling or guaranteed
message delivery