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/*.java
Makefile
, 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/