Skip to content

Commit

Permalink
more updated code samples with tests
Browse files Browse the repository at this point in the history
  • Loading branch information
benrhine committed Oct 10, 2019
1 parent b80457f commit 22303d8
Show file tree
Hide file tree
Showing 18 changed files with 290 additions and 298 deletions.
12 changes: 3 additions & 9 deletions src/main/docs/guide/httpServer/sessions.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ The above configuration enables header resolution, but disables cookie resolutio

A api:session.Session[] object can be retrieved simply by declaring the api:session.Session[] in a controller method signature. For example consider the following controller:

snippet::io.micronaut.docs.session.ShoppingController[tags="imports,class,add", indent=0]
snippet::io.micronaut.docs.session.ShoppingController[tags="imports,class,add,endclass", indent=0]

<1> The `ShoppingController` declares a api:session.Session[] attribute called `cart`
<2> The api:session.Session[] is declared as a parameter to the method
Expand All @@ -85,21 +85,15 @@ If the client is a web browser then sessions should just work if you have cookie
For example, when invoking the `viewCart` method of the `StoreController` in the previous example the HTTP client will receive by default a `AUTHORIZATION_INFO` header. The following example, using a Spock test, demonstrates this:

.Retrieving the AUTHORIZATION_INFO header
[source,groovy]
----
include::{testssession}/ShoppingControllerSpec.groovy[tags=view, indent=0]
----
snippet::io.micronaut.docs.session.ShoppingControllerSpec[tags="view", indent=0]

<1> A request is made to `/shopping/cart`
<2> The `AUTHORIZATION_INFO` header is present in the response

You can then pass this `AUTHORIZATION_INFO` in subsequent requests to re-use the existing api:session.Session[]:

.Sending the AUTHORIZATION_INFO header
[source,groovy]
----
include::{testssession}/ShoppingControllerSpec.groovy[tags=add, indent=0]
----
snippet::io.micronaut.docs.session.ShoppingControllerSpec[tags="add", indent=0]

<1> The `AUTHORIZATION_INFO` is retrieved from the response
<2> And then sent as a header in the subsequent request
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package io.micronaut.docs.server.sse

import io.micronaut.http.annotation.Controller;

// tag::imports[]

import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import io.micronaut.http.sse.Event
import io.reactivex.Emitter
Expand All @@ -30,14 +28,14 @@ class HeadlineController {
if (i < versions.length) {
emitter.onNext( // <4>
Event.of(new Headline("Micronaut " + versions[i] + " Released", "Come and get it"))
);
)
} else {
emitter.onComplete(); // <5>
emitter.onComplete() // <5>
}
return ++i;
return ++i
}

return Flowable.generate(initialState, emitterFunction as BiFunction<Integer,Emitter<Event<Headline>>,Integer>);
return Flowable.generate(initialState, emitterFunction as BiFunction<Integer,Emitter<Event<Headline>>,Integer>)
}
}
// end::class[]
Original file line number Diff line number Diff line change
@@ -1,18 +1,3 @@
/*
* Copyright 2017-2019 original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.micronaut.docs.server.sse

import io.micronaut.context.ApplicationContext
Expand All @@ -21,15 +6,10 @@ import io.micronaut.http.client.sse.RxSseClient
import io.micronaut.http.sse.Event
import io.micronaut.runtime.server.EmbeddedServer
import spock.lang.AutoCleanup
import spock.lang.Ignore
import spock.lang.Shared
import spock.lang.Specification
import spock.util.concurrent.PollingConditions

/**
* @author Graeme Rocher
* @since 1.0
*/
class HeadlineControllerSpec extends Specification {

@Shared @AutoCleanup EmbeddedServer embeddedServer =
Expand All @@ -53,5 +33,4 @@ class HeadlineControllerSpec extends Specification {
events[0].data.description == "Come and get it"
}
}

}
Original file line number Diff line number Diff line change
@@ -1,22 +1,17 @@

package io.micronaut.docs.session;
package io.micronaut.docs.session

// tag::imports[]

import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.Post;
import io.micronaut.session.Session;
import io.micronaut.session.annotation.SessionValue;
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import io.micronaut.http.annotation.Post
import io.micronaut.session.Session
import io.micronaut.session.annotation.SessionValue

import javax.annotation.Nullable;
import javax.validation.constraints.NotBlank;
import javax.annotation.Nullable
import javax.validation.constraints.NotBlank
// end::imports[]

/**
* @author graemerocher
* @since 1.0
*/
// tag::class[]
@Controller("/shopping")
class ShoppingController {
Expand All @@ -42,7 +37,7 @@ class ShoppingController {
session.put(ATTR_CART, newCart) // <4>
newCart
})
cart.getItems().add(name);
cart.getItems().add(name)
cart
}
// end::add[]
Expand All @@ -55,4 +50,7 @@ class ShoppingController {
}
}
// end::clear[]

// tag::endclass[]
}
// end::endclass[]
Original file line number Diff line number Diff line change
@@ -1,18 +1,3 @@
/*
* Copyright 2017-2019 original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.micronaut.docs.session

import io.micronaut.context.ApplicationContext
Expand All @@ -25,10 +10,6 @@ import spock.lang.AutoCleanup
import spock.lang.Shared
import spock.lang.Specification

/**
* @author graemerocher
* @since 1.0
*/
class ShoppingControllerSpec extends Specification {

@Shared @AutoCleanup EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,25 @@ package io.micronaut.docs.server.filters
import io.kotlintest.shouldBe
import io.kotlintest.specs.StringSpec
import io.micronaut.context.ApplicationContext
import io.micronaut.context.env.Environment
import io.micronaut.docs.server.intro.HelloControllerSpec
import io.micronaut.http.HttpRequest
import io.micronaut.http.client.RxHttpClient
import io.micronaut.runtime.server.EmbeddedServer
import java.util.HashMap


class TraceFilterSpec: StringSpec() {

val map: HashMap<String, Any> = hashMapOf("spec.name" to HelloControllerSpec::class.java.simpleName, "spec.lang" to "java")

val embeddedServer = autoClose(
ApplicationContext.run(EmbeddedServer::class.java, map, Environment.TEST)
ApplicationContext.run(EmbeddedServer::class.java,
mapOf("spec.name" to HelloControllerSpec::class.java.simpleName, "spec.lang" to "java"))
)

val client = autoClose(
embeddedServer.applicationContext.createBean(RxHttpClient::class.java, embeddedServer.getURL())
embeddedServer.applicationContext.createBean(RxHttpClient::class.java, embeddedServer.url)
)

init {
"test trace filter"() {
"test trace filter" {
val response = client.toBlocking().exchange<Any, Any>(HttpRequest.GET("/hello"))

response.headers.get("X-Trace-Enabled") shouldBe "true"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package io.micronaut.docs.server.sse

// tag::class[]
class Headline {
var title: String? = null
var description: String? = null

constructor() {}

constructor(title: String, description: String) {
this.title = title
this.description = description
}
}
// end::class[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.micronaut.docs.session

import java.util.ArrayList

class Cart {

var items: MutableList<String> = ArrayList()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package io.micronaut.docs.session

// tag::imports[]

import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import io.micronaut.http.annotation.Post
import io.micronaut.session.Session
import io.micronaut.session.annotation.SessionValue

// end::imports[]

// tag::class[]
@Controller("/shopping")
class ShoppingController {
// end::class[]

companion object {
private const val ATTR_CART = "cart" // <1>
}

// tag::view[]
@Get("/cart")
@SessionValue(ATTR_CART) // <1>
internal fun viewCart(@SessionValue cart: Cart?): Cart { // <2>
var cart = cart
if (cart == null) {
cart = Cart()
}
return cart
}
// end::view[]

// tag::add[]
@Post("/cart/{name}")
internal fun addItem(session: Session, name: String): Cart { // <2>
require(name.isNotBlank()) { "Name cannot be blank" }
val cart = session.get(ATTR_CART, Cart::class.java).orElseGet({
// <3>
val newCart = Cart()
session.put(ATTR_CART, newCart) // <4>
newCart
})
cart.items.add(name)
return cart
}
// end::add[]

// tag::clear[]
@Post("/cart/clear")
internal fun clearCart(session: Session?) {
session?.remove(ATTR_CART)
}
// end::clear[]

// tag::endclass[]
}
// end::endclass[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package io.micronaut.docs.session

import io.kotlintest.shouldBe
import io.kotlintest.specs.StringSpec
import io.micronaut.context.ApplicationContext
import io.micronaut.http.HttpHeaders
import io.micronaut.http.HttpRequest
import io.micronaut.http.client.RxHttpClient
import io.micronaut.runtime.server.EmbeddedServer
import kotlin.test.assertNotNull


class ShoppingControllerSpec: StringSpec() {

val embeddedServer = autoClose(
ApplicationContext.run(EmbeddedServer::class.java)
)

val client = autoClose(
embeddedServer.applicationContext.createBean(RxHttpClient::class.java, embeddedServer.url)
)

init {
"testSessionValueUsedOnReturnValue" {
// tag::view[]
var response = client.exchange(HttpRequest.GET<Cart>("/shopping/cart"), Cart::class.java) // <1>
.blockingFirst()
var cart = response.body()

assertNotNull(response.header(HttpHeaders.AUTHORIZATION_INFO)) // <2>
assertNotNull(cart)
cart.items.isEmpty()
// end::view[]

// tag::add[]
val sessionId = response.header(HttpHeaders.AUTHORIZATION_INFO) // <1>

response = client.exchange(
HttpRequest.POST("/shopping/cart/Apple", "")
.header(HttpHeaders.AUTHORIZATION_INFO, sessionId), Cart::class.java) // <2>
.blockingFirst()
cart = response.body()
// end::add[]

assertNotNull(cart)
cart.items.size shouldBe 1

response = client.exchange(HttpRequest.GET<Any>("/shopping/cart")
.header(HttpHeaders.AUTHORIZATION_INFO, sessionId), Cart::class.java)
.blockingFirst()
cart = response.body()

response.header(HttpHeaders.AUTHORIZATION_INFO)
assertNotNull(cart)

cart.items.size shouldBe 1
cart.items[0] shouldBe "Apple"
}
}
}
Loading

0 comments on commit 22303d8

Please sign in to comment.