Java Portal | Программирование
11.9K subscribers
1.63K photos
119 videos
45 files
1.69K links
Присоединяйтесь к нашему каналу и погрузитесь в мир для Java-разработчика

Связь: @devmangx

РКН: https://clck.ru/3H4WUg
Download Telegram
Spring Boot: если в коде используется RestTemplate, тесты можно писать, подменяя внешние HTTP-вызовы с помощью MockRestServiceServer.

✅MockRestServiceServer работает за счет перехвата HTTP-запросов.

Дан сервис, который дергает внешний API:

@Service
public class ProductService {

private final RestTemplate restTemplate;

public ProductService(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}

public String getProductName(long id) {
Product product = restTemplate.getForObject(
"https://remoteapi.com/products/{id}",
Product.class,
id
);
return product.getName();
}
}



Тест можно реализовать так:

@SpringBootTest
class ProductServiceTest {

@Autowired
private RestTemplate restTemplate;

@Autowired
private ProductService productService;

private MockRestServiceServer mockServer;

@BeforeEach
void setup() {
mockServer = MockRestServiceServer.createServer(restTemplate);
}

@Test
void shouldReturnProductWhenExternalApiCalled() {
// Arrange
mockServer.expect(requestTo("https://remoteapi.com/products/1"))
.andExpect(method(HttpMethod.GET))
.andRespond(withSuccess(
"{\"id\":1,\"name\":\"USB stick\"}",
MediaType.APPLICATION_JSON
));

// Act
ProductDto product = productService.getProduct(1L);

// Assert
assertThat(product.getName()).isEqualTo("USB stick");

mockServer.verify();
}
}


👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤4🔥2😁2
Нашли офигенный способ выучить PostgreSQL в браузере : crunchydata

PostgreSQL-песочница с практическими уроками SQL, транзакциям, индексам, PostGIS и не только

🛌

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13❤2😁1
Java: не пихай бизнес-логику в Stream.peek(). Используй его только для отладки.

Смысл простой: peek() предназначен для легкого дебага и просмотра потока, а не для вычислений или побочных эффектов.

Используй только для легкой отладки

Пример: просмотр (инспекция) потока пайплайна

list.stream()
.filter(x -> x > 10)
.peek(x -> System.out.println("Filter: " + x))
.map(x -> x * 2)
.peek(x -> System.out.println("Map: " + x))
.toList();


👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9❤4
Под капотом многопоточной синхронизации в Java: как потоки договариваются через Mark Word

Синхронизация в Java часто воспринимается как простая языковая конструкция — достаточно использовать ключевое слово synchronized, и код начинает «просто работать».

На практике же на уровне JVM происходит цепочка событий, которую можно проследить до Mark Word — восьмибайтового служебного поля заголовка каждого Java-объекта.

Современные JVM (HotSpot, OpenJ9, GraalVM) не используют фиксированную модель блокировок. Вместо этого они динамически выбирают стратегию синхронизации, исходя из реального поведения потоков и истории использования объекта.

Эта статья предназначена для Java‑разработчиков, которые уже знакомы с многопоточностью и synchronized, но хотят разобраться, как именно JVM управляет блокировками, какие состояния проходит объект и какую роль в этом играет Mark Word.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4
Java подсказка : не злоупотребляй наследованием. Когда можно — лучше делегируй. Наследование создаёт сильную связку, и это может выстрелить в ногу, если базовый класс изменится.

Предположим, у нас есть такой класс:

class Engine {
void start() {
}
}


и Car наследуется от Engine:

class Car extends Engine {
void drive() {
start();
}
}


Наследование выражает отношение is, но автомобиль на самом деле не является двигателем, он имеет двигатель. Перепишем через делегацию:

class Car {
private Engine engine;
Car(Engine engine) {
this.engine = engine;
}
void drive() {
engine.start();
}
}


Таким образом эти два класса развязаны, и отношение превращается в has.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤1
А может ли Java гонять TensorFlow без JNI и без Python?

Автор взял Java 25 + FFM и протащил это всё до C-шного TensorFlow API, собрав рабочий REST-сервис на macOS.

Результат: предсказуемая память, нативная производительность и максимально скучная (в хорошем смысле) архитектура.

Ломали когда-нибудь Quarkus-эндпоинт просто тем, что решили залогировать request body?

В этом гайде показывают, как безопасно аудировать, чистить и трассировать HTTP-запросы через request filters в Quarkus, не блокируя обработку и не убивая API.

Практично и можно почти копипастить.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3👀3
Java: не вешай логику в Stream.peek(), используй его только для отладки.

Используй его для легкой отладки

Пример: инспекция потока пайплайна

list.stream()
.filter(x -> x > 10)
.peek(x -> System.out.println("Filter: " + x))
.map(x -> x * 2)
.peek(x -> System.out.println("Map: " + x))
.toList();



👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔3
СХЕМЫ АУТЕНТИФИКАЦИИ

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8👍7🤔2🤣1
Spring Boot. Чтобы Jackson создавал объекты из JSON явно и предсказуемо, можно использовать аннотацию
@JsonCreator

Каждый параметр явно биндится.

Определяем конструктор с @JsonCreator:

class User {
public final String username;
public final int age;

@JsonCreator
public User(
@JsonProperty("username") String username,
@JsonProperty("age") int age
) {
this.username = username;
this.age = age;
}
}


👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
❤11
Многопоточность позволяет писать так, чтобы несколько задач выполнялись параллельно внутри одного приложения.

Чтобы использовать многопоточность (то есть писать многопоточный код), нужен класс java.lang.Thread.

Стадии жизненного цикла потока:

• New: Новый поток начинает жизнь в состоянии new. Он остается там, пока программа не запустит поток.

• Runnable: После запуска новый поток становится runnable. В этом состоянии считается, что поток выполняет свою работу.

• Waiting: Иногда поток переходит в waiting, когда ему нужно дождаться выполнения задачи другим потоком.

• Timed Waiting: Поток из runnable может перейти в timed waiting на определенный промежуток времени. После истечения этого времени он снова возвращается в runnable.

• Terminated: Поток попадает в terminated после завершения задачи или принудительного завершения.

Приоритеты потоков:

Каждый Java-поток имеет приоритет, который помогает ОС решать порядок планирования потоков.

• MIN_PRIORITY (константа 1)
• NORM_PRIORITY (константа 5) (приоритет по умолчанию)
• MAX_PRIORITY (константа 10)

Базовые способы создать поток в Java:

• Реализовать интерфейс Runnable
• Наследоваться от Thread

Методы потоков:

• public void start()
Запускает поток в отдельном пути выполнения и затем вызывает run() у этого объекта Thread.

• public void run()
Если объект Thread был создан с отдельным Runnable, то run() будет вызван на этом Runnable.

• public final void setPriority(int priority)
Устанавливает приоритет потока. Возможные значения от 1 до 10.

• public void interrupt()
Прерывает поток, заставляя продолжить выполнение, даже если он был заблокирован.

• public final boolean isAlive()
Возвращает true, если поток "жив", то есть после старта и до завершения.

Это были базовые вещи. Пост длинный, но надеюсь, что что-то новое унес с собой.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12❤2
Spring Boot. С помощью @DataJpaTest можно прогонять JPA репозитории изолированно.

@DataJpaTest поднимает только JPA слой без всего приложения, использует in-memory базу H2 и откатывает транзакции после каждого теста.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7👍1
Поток обработки запроса в Spring Boot

Вопрос на собеседовании: как проходит HTTP-запрос внутри Spring Boot приложения?

Звучит просто, но на практике сложно правильно восстановить порядок и технические детали.

• клиент отправляет HTTP-запрос
• запрос сначала попадает в DispatcherServlet (Front Controller)
• DispatcherServlet через HandlerMapping ищет нужный контроллер
• контроллер занимается маппингом запроса и валидацией
• бизнес-логика выполняется в сервисном слое
• работа с базой идет через репозиторий (JPA)
• ответ идет обратно по тому же пути и сериализуется в JSON через Jackson

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7👍3
Spring Boot: чтобы прогнать SQL-скрипты до или после выполнения тестового метода, можно использовать аннотацию @Sql.

@SpringBootTest
@Sql("/test/products.sql")
class ProductServiceTest {

@Autowired
ProductService productService;

@Test
void findProductByName() {
Product product = productService.findByName("product1");
assertThat(product).isNotNull();
}
}


👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Что такое Throwable

Throwable в Java — это базовый класс для всех «бросаемых» аномалий. Он даёт общий функционал для работы с исключениями: стек, причину, вложенные ошибки и т. д.

С точки зрения модели: невосстанавливаемые критические состояния представлены через Error, а ошибки уровня приложения — через Exception.

То есть всё, что можно бросать (throw), наследуется от Throwable.

Коротко:

Error: обычно невосстанавливаемая и не предполагается обработка на уровне приложения
Exception: приложение может предусматривать и обрабатывать

checked: обработка контролируется компилятором
unchecked: обработка не принудительная

Иерархия выглядит примерно так:

java.lang.Object
└─ java.lang.Throwable // всё, что можно throw-нуть
├─ java.lang.Error // системные критические сбои
│ ├─ OutOfMemoryError
│ ├─ StackOverflowError
│ ├─ VirtualMachineError
│ └─ ...
└─ java.lang.Exception // исключения уровня приложения
├─ RuntimeException // unchecked
│ ├─ NullPointerException
│ ├─ IllegalArgumentException
│ ├─ IndexOutOfBoundsException
│ └─ ...
└─ IOException, SQLException (checked)


Разница между Error и Exception


Error — «фатальный и невосстанавливаемый сбой»
Exception — «аномалия, которую приложение может ожидать и обрабатывать»

Мини сравнение:

источник: Error приходит от JVM и рантайма, Exception рождается на уровне приложения
восстановление: у Error почти нулевые шансы, у Exception всё зависит от ситуации
catch: Error обычно не ловят, Exception ловят и обрабатывают
примеры: для Error — OOM, StackOverflow; для Exception — неверный ввод или I/O ошибки

Что такое Error

Это фатальные сбои JVM.
Не то, что будут фиксить в бизнес-логике.

Примеры: OutOfMemoryError, StackOverflowError, VirtualMachineError

Почему их не ловят?

предпосылки работы программы уже нарушены
даже если поймать — непонятно, что делать дальше
нормальная стратегия — дать процессу упасть

Что такое Exception

Это исключения, которые приложение может предусматривать и включать в контрольный поток.

checked: IOException, SQLException
unchecked: NullPointerException, IllegalArgumentException

Почему их обрабатывают?
Потому что они «возможны по контракту» — неверный ввод, I/O, бизнес-валидация и т. д.

Почему в GlobalExceptionHandler не ловят Throwable

Потому что обработка Throwable приводила бы к поглощению Error (фатальных ошибок), и приложение продолжило бы работать в «сломанных» условиях.

Подробности:

➡️Поглощение Error
Если OutOfMemoryError превратить в обычный 500, то это попытка «делать вид, что всё ок», в то время как приложение фактически в предсмертном состоянии.

➡️Ломается контрольный поток фреймворка
Например, в Spring разное поведение завязано на тип исключения. Throwable ломает эти правила.

➡️Падает наблюдаемость
«Ловить всё» засоряет логи шумом и усложняет поиск корня проблемы.

Отсюда правило: в GlobalExceptionHandler ловят не Throwable, а Exception (или RuntimeException) как конечный уровень обработки в приложении.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9
Spring Boot: можно переопределять конфиги на рантайме без перепаковки приложения.

Spring Boot по умолчанию использует лаунчер JarLauncher, который позволяет переопределить дефолтную конфигурацию через параметр loader.path при запуске приложения.

Предположим, у вас есть Spring Boot приложение со следующими зависимостями:

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>


С application.properties такого вида:

demo.message=Hello from inside the JAR


И простой контроллер:

@RestController
public class HelloController {

@Value("${demo.message}")
private String message;

@GetMapping("/")
public String hello() {
return message;
}
}


Если собрать jar и запустить:

java -jar springboot-propertieslauncher-demo-0.0.1-SNAPSHOT.jar


Открыв [http://localhost:8080](http://localhost:8080) вы получите:

Hello from inside the JAR


Если теперь создать внешний файл application.properties в той же директории, где лежит jar:

demo.message=Hello from outside the JAR


И запустить приложение с параметром loader.path, указывающим на текущую директорию:

java -jar springboot-propertieslauncher-demo-0.0.1-SNAPSHOT.jar --loader.path=.


Перейдя в [http://localhost:8080](http://localhost:8080) будет:

Hello from outside the JAR


👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10👍3
JetBrains вбросили загадку про IntelliJ IDEA. Судя по всему, кто-то пытается незаметно попасть на их день рождения. Команда решила устроить мини-квест: каждый день будет новая задачка, новые подсказки и в итоге надо вычислить тайного гостя вечеринки. 😂

В первом задании предлагают сопоставить сниппеты кода с версиями Java. Там набор вполне узнаваемых фич: var, streams, diamond-оператор, enum и records. Ниже варианты: Java 5, 7, 8, 11, 17 и 21.

Выглядит легко, но подана история забавно, а оформление в стиле карты-загадки.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6👍4
Новый способ регистрировать бины программно начиная со Spring Framework 7 👇👇👇

@Configuration
@Import(ExampleRegistrar.class)
class ExampleConfiguration {
}

class ExampleRegistrar implements BeanRegistrar {

@Override
public void register(BeanRegistry registry, Environment env) {
if (env.matchesProfiles("dev")) {
registry.registerBean(ExampleInMemoryRepository.class);
} else {
registry.registerBean(ExampleRepository.class);
}
}
}


👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10❤2🔥2
В старые времена на Java самое дорогое выражение, которое я видел в проде, выглядело невинно:

→ repository.findAll()

Компилируется, тесты проходит, на QA тоже всё ок потому что данных мало.

А потом в проде прилетает реальный трафик, JVM начинает пухнуть от хипа и p99 улетает в космос. Причина простая — вызов неограниченный по объёму. Без лимитов, без пагинации, без стриминга.

показательный случай про цену подобных ошибок:

• ракета Ariane 5
• стоимость проекта — 370 млн
• в коде было преобразование 64-битного значения к 16-битному
• при ускорении значение вышло за пределы
• произошёл overflow, навигация отказала
• запуск провалился, 370 млн просто улетели

Вывод: неограниченные операции в коде — всегда риск.

Из той же категории:

• collect(toList()) на огромных стримах
• @Transactional прямо на контроллерах
• synchronized на нагруженном месте

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👀9👍7
Java-совет : выносите повторяющуюся логику в небольшие вспомогательные классы, но не скатывайтесь в всезнающие God-классы.

Пример helper-класса:

public class TextUtils {
public static String capitalize(String str) {
...
}
...
}


А вот это уже God-класс:

public class DoThings {
public void addTask(String task) { ... }
public void saveToFile(String filename) { ... }
public void logError(String error) { ... }
...
}


Он делает слишком много несвязанных вещей.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤4🤣1
Реализация гексагональной архитектуры на Java

В данной статье рассматривается архитектура проекта, позволяющая модульным образом интегрировать инфраструктурные фреймворки, такие как Spring, Quarkus и Micronaut, без необходимости модификации ядра предметной области (domain) или внешних API.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5❤3