FROM baseimage # always first command in a dockerfile WORKDIR </path> # directory where the commands in this file are executed COPY <src> <dest> # copies a file, <src> may contain wildcards RUN <command> # runs a command in a shell, usually linux syntax CMD <command> <param1> <param2> # default for executing container, there may only be one CMD instruction
FROM baseimage # always first command in a dockerfile
WORKDIR </path> # directory where the commands in this file are executed
COPY <src> <dest> # copies a file, <src> may contain wildcards
RUN <command> # runs a command in a shell, usually linux syntax
CMD <command> <param1> <param2> # default for executing container, there may only be one CMD instruction
/: /home/user/documents/eist/practice/h01/build/libs/*.jar/: build/libs/*.jar. simply means "here" (e.g. COPY app.jar . copies app.jar to the root of the directory without renaming
it)/*
STEP 1:
Send POST-request by creating a corresponding ResponseEntity using postForEntity() of RestTemplate
*/
public void postMethod(Object parameter){
ResponseEntity<Class> response = rest.postForEntity(URL_STRING, HTTP_ENTITY, CLASS);
}
/*
STEP 1:
Send POST-request by creating a corresponding ResponseEntity using postForEntity() of RestTemplate
*/
public void postMethod(Object parameter){
ResponseEntity<Class> response = rest.postForEntity(URL_STRING, HTTP_ENTITY, CLASS);
}
/*
STEP 2:
Handle POST-requests accordingly using method with same name in a @RestController-Class
*/
@RestController
@RequestMapping(value = "/whatever/", consumes = "application/json")
public class InboxResource {
@PostMapping("whatever")
public ResponseEntity<String> postMethod(@RequestBody Object parameter){
return new ResponseEntity<>(parameter, HttpStatus.OK);
}
}
/*
STEP 2:
Handle POST-requests accordingly using method with same name in a @RestController-Class
*/
@RestController
@RequestMapping(value = "/whatever/", consumes = "application/json")
public class InboxResource {
@PostMapping("whatever")
public ResponseEntity<String> postMethod(@RequestBody Object parameter){
return new ResponseEntity<>(parameter, HttpStatus.OK);
}
}
/*
STEP 3:
Replace synchronous methods with async counterparts using CompleteableFuture.supplyAsync
*/
// sync version, example given with produce()-method
@PostMapping("whatever")
public ResponseEntity<Object> postMethodOld(@RequestBody Object parameter) {
return new ResponseEntity<>(factory.produce(parameter), HttpStatus.OK);
}
// async version, example given with produce()-method and string return type
@PostMapping("whatever")
public CompletableFuture<String> postMethodAsync(@RequestBody Object parameter) {
return CompletableFuture.supplyAsync(() -> factory.produce(parameter).getName());
}
/*
STEP 3:
Replace synchronous methods with async counterparts using CompleteableFuture.supplyAsync
*/
// sync version, example given with produce()-method
@PostMapping("whatever")
public ResponseEntity<Object> postMethodOld(@RequestBody Object parameter) {
return new ResponseEntity<>(factory.produce(parameter), HttpStatus.OK);
}
// async version, example given with produce()-method and string return type
@PostMapping("whatever")
public CompletableFuture<String> postMethodAsync(@RequestBody Object parameter) {
return CompletableFuture.supplyAsync(() -> factory.produce(parameter).getName());
}
/*
STEP 3.5:
Reroute methods in client class.
*/
// sync version
public Object produceSync() {
var request = createHttpEntity(STRINGNAME);
return rest.postForObject(BASE_URL + PARAM, request, Object.class);
}
// async version
public void produceAsync(InboxClient client) {
CompletableFuture<String> message =
CompletableFuture.supplyAsync(
() -> rest.postForObject(BASE_URL + PARAM, createHttpEntity(STRINGNAME), String.class)
);
try {
client.ready(message.get());
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
/*
STEP 3.5:
Reroute methods in client class.
*/
// sync version
public Object produceSync() {
var request = createHttpEntity(STRINGNAME);
return rest.postForObject(BASE_URL + PARAM, request, Object.class);
}
// async version
public void produceAsync(InboxClient client) {
CompletableFuture<String> message =
CompletableFuture.supplyAsync(
() -> rest.postForObject(BASE_URL + PARAM, createHttpEntity(STRINGNAME), String.class)
);
try {
client.ready(message.get());
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
// GET, POST, PUT and DELETE functions (CRUD)
@GetMapping("endpoint_dir")
public ResponseEntity<List<Object>> getObjects(@RequestParam(name = "name", defaultValue = value)...) {
return ResponseEntity.ok(objectService.getAllObjects());
}
@PostMapping("endpoint_dir")
public ResponseEntity<Object> createObject(@RequestBody Object object) {
if (condition) { // most likely object.getId() != null
return ResponseEntity.badRequest().build();
}
return ResponseEntity.ok(objectService.saveObject(object));
}
@PutMapping("endpoint_dir/{object_id}")
public ResponseEntity<Object> updateObject(
@RequestBody Object updatedObject,
@PathVariable("object_id") UUID objectId) {
if (condition) { // most likely !updatedObject.getId().equals(objectId)
return ResponseEntity.badRequest().build();
}
return ResponseEntity.ok(objectService.saveObject(updatedObject));
}
@DeleteMapping("endpoint_dir/{object_id}")
public ResponseEntity<Void> deleteObject(@PathVariable("object_id") UUID objectId) {
objectService.deleteObject(objectId);
return ResponseEntity.noContent().build();
}
// GET, POST, PUT and DELETE functions (CRUD)
@GetMapping("endpoint_dir")
public ResponseEntity<List<Object>> getObjects(@RequestParam(name = "name", defaultValue = value)...) {
return ResponseEntity.ok(objectService.getAllObjects());
}
@PostMapping("endpoint_dir")
public ResponseEntity<Object> createObject(@RequestBody Object object) {
if (condition) { // most likely object.getId() != null
return ResponseEntity.badRequest().build();
}
return ResponseEntity.ok(objectService.saveObject(object));
}
@PutMapping("endpoint_dir/{object_id}")
public ResponseEntity<Object> updateObject(
@RequestBody Object updatedObject,
@PathVariable("object_id") UUID objectId) {
if (condition) { // most likely !updatedObject.getId().equals(objectId)
return ResponseEntity.badRequest().build();
}
return ResponseEntity.ok(objectService.saveObject(updatedObject));
}
@DeleteMapping("endpoint_dir/{object_id}")
public ResponseEntity<Void> deleteObject(@PathVariable("object_id") UUID objectId) {
objectService.deleteObject(objectId);
return ResponseEntity.noContent().build();
}
private final WebClient webClient; // web client to handle REST requests
private final List<Object> objects; // private, local list of objects to be stored
public ObjectController(){
this.webClient = WebClient.builder()
.baseUrl("http://localhost:8080/") // insert URL here
.defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.build();
this.objects = new ArrayList<>();
}
// POST
public void addObject(Object object, Consumer<List<Object>> objectConsumer) {
webClient.post()
.uri("endpoint_dir")
.bodyValue(object)
.retrieve()
.bodyToMono(Object.class)
.onErrorStop()
.subscribe(newObject -> {
objects.add(newObject);
objectConsumer.accept(objects);
});
}
// PUT
public void updateObject(Object object, Consumer<List<Object>> objectConsumer) {
webClient.put()
.uri("endpoint_dir/" + object.getId())
.bodyValue(object)
.retrieve()
.bodyToMono(Object.class)
.onErrorStop()
.subscribe(newObject -> {
objects.replaceAll(oldObject -> oldObject.getId().equals(newObject.getId()) ? newObject : oldObject);
objectConsumer.accept(objects);
});
}
// DELETE
public void deleteObject(Object object, Consumer<List<Object>> objectConsumer) {
webClient.delete()
.uri("endpoint_dir/" + object.getId())
.retrieve()
.toBodilessEntity()
.onErrorStop()
.subscribe(x -> {
objects.remove(object);
objectConsumer.accept(objects);
});
}
// GET
public void getAllObjects(Consumer<List<Object>> objectConsumer, QueryParam...) {
webClient.get()
.uri(uriBuilder -> uriBuilder
.path("endpoint_dir")
.queryParam("paramName", paramValue) // can be repeated however many times needed
.build())
.retrieve()
.bodyToMono(new ParameterizedTypeReference<List<Object>>() {})
.onErrorStop()
.subscribe(newObjects -> {
objects.clear();
objects.addAll(newObjects);
objectsConsumer.accept(objects);
});
}
private final WebClient webClient; // web client to handle REST requests
private final List<Object> objects; // private, local list of objects to be stored
public ObjectController(){
this.webClient = WebClient.builder()
.baseUrl("http://localhost:8080/") // insert URL here
.defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.build();
this.objects = new ArrayList<>();
}
// POST
public void addObject(Object object, Consumer<List<Object>> objectConsumer) {
webClient.post()
.uri("endpoint_dir")
.bodyValue(object)
.retrieve()
.bodyToMono(Object.class)
.onErrorStop()
.subscribe(newObject -> {
objects.add(newObject);
objectConsumer.accept(objects);
});
}
// PUT
public void updateObject(Object object, Consumer<List<Object>> objectConsumer) {
webClient.put()
.uri("endpoint_dir/" + object.getId())
.bodyValue(object)
.retrieve()
.bodyToMono(Object.class)
.onErrorStop()
.subscribe(newObject -> {
objects.replaceAll(oldObject -> oldObject.getId().equals(newObject.getId()) ? newObject : oldObject);
objectConsumer.accept(objects);
});
}
// DELETE
public void deleteObject(Object object, Consumer<List<Object>> objectConsumer) {
webClient.delete()
.uri("endpoint_dir/" + object.getId())
.retrieve()
.toBodilessEntity()
.onErrorStop()
.subscribe(x -> {
objects.remove(object);
objectConsumer.accept(objects);
});
}
// GET
public void getAllObjects(Consumer<List<Object>> objectConsumer, QueryParam...) {
webClient.get()
.uri(uriBuilder -> uriBuilder
.path("endpoint_dir")
.queryParam("paramName", paramValue) // can be repeated however many times needed
.build())
.retrieve()
.bodyToMono(new ParameterizedTypeReference<List<Object>>() {})
.onErrorStop()
.subscribe(newObjects -> {
objects.clear();
objects.addAll(newObjects);
objectsConsumer.accept(objects);
});
}
// via Runnable
public class MyRunnable implements Runnable{
public int integer = 0;
public void run(){
System.out.println("Integer: " + integer++);
}
}
public class Main{
public static void main(String[] args){
// with custom, explicit runnable
Runnable r = new MyRunnable();
Thread t = new Thread(r);
t.start();
t.join(); // surround with try...catch...
// def run() method of runnable in lambda
Thread t1 = new Thread(() -> {
System.out.println("Lambda!");
});
t1.start();
}
}
// via Runnable
public class MyRunnable implements Runnable{
public int integer = 0;
public void run(){
System.out.println("Integer: " + integer++);
}
}
public class Main{
public static void main(String[] args){
// with custom, explicit runnable
Runnable r = new MyRunnable();
Thread t = new Thread(r);
t.start();
t.join(); // surround with try...catch...
// def run() method of runnable in lambda
Thread t1 = new Thread(() -> {
System.out.println("Lambda!");
});
t1.start();
}
}
lockObject.lock();
try {
// statements
}
finally {
lockObject.unlock();
}
lockObject.lock();
try {
// statements
}
finally {
lockObject.unlock();
}
// buffer object
class Buffer {
Semaphore free;
Semaphore occupied;
}
// producer thread
produce(){
free.acquire();
synchronized(Buffer){
...
}
occupied.release();
}
// consumer thread
consume(){
occupied.acquire();
synchronized(Buffer){
...
}
free.release();
}
// buffer object
class Buffer {
Semaphore free;
Semaphore occupied;
}
// producer thread
produce(){
free.acquire();
synchronized(Buffer){
...
}
occupied.release();
}
// consumer thread
consume(){
occupied.acquire();
synchronized(Buffer){
...
}
free.release();
}
@Test public void exampleTest(): identifies that exampleTest() is a test method@Timeout(value = x, unit = TimeUnit.y): test automatically
fails after x units of time@BeforeEach void setup(): method gets executed before
every test (i.e. multiple times for each test)@AfterEach void teardown(): method gets executed after
every test@BeforeAll static void setup(): code only gets executed
once at instantiation of class (before all tests)@AfterAll static void teardown(): code only gets executed
once after removal of class (after all tests)@Disable: disables testassertTrue(condition, message): checks if condition is trueassertFalse(condition, message: checks if condition is falseassertEquals(expected, actual, message): checks if values /
objects expected and actual are equalassertEquals(expected, actual, delta, message): for floats
and doubles, with error margin deltafail(message): fails the testassertNull(object, message): checks if object is
nullassertNotNull(object, message): checks if object is
not nullassertSame(expected, actual, message): check is expected and actual refer
to the same objectassertNotSame(expected, actual, message): check is expected and actual
do not refer to the same objectassertThrows(expectedType, executable, message): check that
execution of the supplied executable (e.g. lambda expression) throws an exception
of the expectedType and returns the exception@Mock // mock object
Object mockObject;
@TestSubject // SUT
Object testSubject = new Object();
@Test
public void test() {
expect(mockObject.function()).andReturn(returnValue);
replay(mockObject);
// insert test as usual here
verify(mockObject);
}
@Mock // mock object
Object mockObject;
@TestSubject // SUT
Object testSubject = new Object();
@Test
public void test() {
expect(mockObject.function()).andReturn(returnValue);
replay(mockObject);
// insert test as usual here
verify(mockObject);
}
infer run -- javac src/de/tum/in/ase/eist/*.javaMakefile, add -fsanitize=address to
gcc instruction
free()
(heap-use-after-free)// add plugins
plugins {
id 'sth.etc.pluginname.morethings' version 'version_number'
}
// add dependencies
// easy way: intellij bottom bar -> dependencies -> search and add -> reload
// manual labor:
dependencies {
implementation 'ins.ert.coolname.here'
testimplementation 'sth.to.do.withjunitprobably'
}
// directories
sourceSets {
main {
java {
srcDir 'src'
}
}
test {
java {
srcDir 'test'
}
}
}
// see project repositories for full gradle build files if necessary
// add plugins
plugins {
id 'sth.etc.pluginname.morethings' version 'version_number'
}
// add dependencies
// easy way: intellij bottom bar -> dependencies -> search and add -> reload
// manual labor:
dependencies {
implementation 'ins.ert.coolname.here'
testimplementation 'sth.to.do.withjunitprobably'
}
// directories
sourceSets {
main {
java {
srcDir 'src'
}
}
test {
java {
srcDir 'test'
}
}
}
// see project repositories for full gradle build files if necessary
// example: L10H01
// subclasses: PhysicalTutorGroupMeeting and VirtualTutorGroupMeeting
public abstract class TutorGroupMeeting {
// common attributes go here...
public void practice(){ // MOVED FUNCTION OF SUBCLASSES THAT GETS CALLED
Student tutor = getTutorGroup().getTutor();
greet(tutor); // SUBCLASS-DEFINED
session(tutor); // IMPLEMENTED HERE
end(tutor); // SUBCLASS-DEFINED
}
// common getters and setters go here...
public abstract void greet(Student tutor); // TO BE IMPLEMENTED IN SUBCLASS
public void session(Student tutor){ // IMPLEMENTED HERE
// identical code in both subclasses goes here...
}
public abstract void end(Student tutor); // TO BE IMPLEMENTED IN SUBCLASS
}
// example: L10H01
// subclasses: PhysicalTutorGroupMeeting and VirtualTutorGroupMeeting
public abstract class TutorGroupMeeting {
// common attributes go here...
public void practice(){ // MOVED FUNCTION OF SUBCLASSES THAT GETS CALLED
Student tutor = getTutorGroup().getTutor();
greet(tutor); // SUBCLASS-DEFINED
session(tutor); // IMPLEMENTED HERE
end(tutor); // SUBCLASS-DEFINED
}
// common getters and setters go here...
public abstract void greet(Student tutor); // TO BE IMPLEMENTED IN SUBCLASS
public void session(Student tutor){ // IMPLEMENTED HERE
// identical code in both subclasses goes here...
}
public abstract void end(Student tutor); // TO BE IMPLEMENTED IN SUBCLASS
}
git pull --rebase=false to use merginggit pull --rebase=true to use rebasing (not
recommended for lecture scope)Summary by Flavius Schmidt, ge83pux, 2023.
https://home.in.tum.de/~scfl/