Unable to resolve java build / Spring - java

First Thing to say, I am a relatively inexperienced programmer.
My task is to import a given gradle project into Spring Boot Tool Suite (sts). I have already download springboot cli, java, gradle. & In the past, I was able to run spring perfectly on another project, unfortunately I had to get my hard drive replaced, so I lost a considerable amount of downloads.
Nonetheless, my issue is two-parted. Firstly, my tool suite (ide? It's basically eclipse) does not recognize my project as a a java project, I have tried many options & the only was to fix that portion is to hardcode org.eclipse.core.javabuilder within the buildCommand tag in my .project file, which I don't remember doing for my last project.
Here is the directory tree of the backend folder(don't concern with the frontend)
.
├── build.gradle
├── gradle
│   └── wrapper
│   ├── gradle-wrapper.jar
│   └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src
├── main
│   ├── java
│   │   └── ca
│   │   └── mcgill
│   │   └── ecse321
│   │   └── eventregistration
│   │   ├── EventRegistrationApplication.java
│   │   ├── controller
│   │   │   ├── ApiError.java
│   │   │   ├── EventRegistrationRestController.java
│   │   │   └── RestExceptionHandler.java
│   │   ├── dao
│   │   │   ├── EventRegistrationRepository.java
│   │   │   ├── EventRepository.java
│   │   │   ├── PersonRepository.java
│   │   │   └── RegistrationRepository.java
│   │   ├── dto
│   │   │   ├── EventDto.java
│   │   │   ├── PersonDto.java
│   │   │   └── RegistrationDto.java
│   │   ├── model
│   │   │   ├── Event.java
│   │   │   ├── Person.java
│   │   │   ├── Registration.java
│   │   │   └── RegistrationManager.java
│   │   └── service
│   │   └── EventRegistrationService.java
│   └── resources
│   └── application.properties
└── test
└── java
└── ca
└── mcgill
└── ecse321
└── eventregistration
└── service
├── event
│   └── TestCinema.java
├── payment
│   ├── TestPaymentWithCreditCard.java
│   ├── TestPaymentWithCreditCardData.java
│   └── TestUtils.java
└── role
├── PromoterRoleTestData.java
└── TestPromoterRole.java
Additionally, Here it my build.gradle file
buildscript {
ext {
springBootVersion = '2.1.2.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
runtimeOnly 'org.postgresql:postgresql'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
This fixes my java problem, but I still cannot get it running as a spring boot application.
Please help as I am not sure where to continue!!! I need to be able to run this project as a spring boot application for backend services, as I will then be tasked with connecting it to frontend services with vue.js. (Don't worry i got that part)!
Here is my EventRegistration.java file as well
package ca.mcgill.ecse321.eventregistration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.SpringApplication;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
#RestController
#SpringBootApplication
public class EventRegistrationApplication {
public static void main(String[] args) {
SpringApplication.run(EventRegistrationApplication.class, args);
}
#RequestMapping("/")
public String greeting() {
return "ECSE321 Event Registration Application - Backend base URL.\n"
+ "Use the API methods to interact with the backend!";
}
}

Though I stopped using eclipse but following used to solve situations like this
1.
- Eclipse ->preferences-->java-->installed JRE --> select a standard vm
(can find here jdk1.8.0_51.jdk/Contents/Home)
2.
- add the JRE System Library to your project build path
- right click project > select build path > libraries >
- if JRE is listed then good otherwise > add Library
- select JRE library and finish

Related

Gradle task does not accept Java user input

I utilised springboot to create a gradle project MortgageCalculator. After building the project with ./gradlew build I have the following directory tree:
.
├── build
│   ├── classes
│   │   └── java
│   │   ├── main
│   │   │   └── com
│   │   │   └── tian
│   │   │   └── MortgageCalculator
│   │   │   ├── DemoApplication.class
│   │   │   └── Main.class
│   │   └── test
│   │   └── com
│   │   └── tian
│   │   └── MortgageCalculator
│   │   └── DemoApplicationTests.class
| ...
|
├── build.gradle
|
|
...
|
└── src
├── main
│   ├── java
│   │   └── com
│   │   └── tian
│   │   └── MortgageCalculator
│   │   ├── DemoApplication.java
│   │   └── Main.java
│   └── resources
│   └── application.properties
...
The source code for Main.java is
package com.tian.MortgageCalculator;
import java.util.Scanner;
public class Main {
public static void main (String[] args) {
// initialising tools
Scanner scanner = new Scanner(System.in);
byte a = scanner.nextByte();
}
}
I then define a task within build.gradle
task Main(type: JavaExec) {
main = 'com.tian.MortgageCalculator.Main'
classpath = sourceSets.main.runtimeClasspath
}
But when I run ./gradlew Main. I get the following exception
Exception in thread "main" java.util.NoSuchElementException
at java.base/java.util.Scanner.throwFor(Scanner.java:937)
at java.base/java.util.Scanner.next(Scanner.java:1594)
at java.base/java.util.Scanner.nextByte(Scanner.java:2002)
at java.base/java.util.Scanner.nextByte(Scanner.java:1956)
at com.tian.MortgageCalculator.Main.main(Main.java:14)
I think the problem is that running a task this way does not allow for user input into the system in, but how should I define my task to allow it?
You’re probably looking for the standardInput property of the JavaExec task type. Using the following task definition, the setup worked for me (tested with Gradle 6.8.2):
task Main(type: JavaExec) {
main = 'com.tian.MortgageCalculator.Main'
classpath = sourceSets.main.runtimeClasspath
standardInput = System.in
}

Annotation proccessor configuration from a Gradle multi module build in IntelliJ 2019.3 seems not to work correctly

I have a Gradle multi module project that uses the Mapstruct annotation processor for data type mapping across Java modules. The Gradle build works fine but when I import the project into IntellJ IDEA 2019.3 I get an unexpected annotation processor configuration.
The project structure looks like this
.
├── build.gradle
├── module1
│   └── src
│   └── main
│   └── java
│   └── io
│   └── wangler
│   └── mapstruct
│   ├── ApplicationModule1.java
│   ├── Person.java
│   ├── PersonDTO.java
│   └── PersonMapper.java
├── module2
│   └── src
│   └── main
│   ├── generated
│   │   └── ch
│   │   └── silviowangler
│   │   └── mapstruct
│   │   └── CarMapperImpl.java
│   └── java
│   └── ch
│   └── silviowangler
│   └── mapstruct
│   ├── ApplicationModule2.java
│   ├── Car.java
│   ├── CarDTO.java
│   └── CarMapper.java
└── settings.gradle
and the build.gradle that registers the annotation processor for module1 and module2.
subprojects { p ->
apply plugin: 'java-library'
apply plugin: 'groovy'
repositories {
jcenter()
}
dependencies {
annotationProcessor 'org.mapstruct:mapstruct-processor:1.3.1.Final'
implementation 'org.mapstruct:mapstruct:1.3.1.Final'
testImplementation 'org.codehaus.groovy:groovy-all:2.5.8'
testImplementation 'org.spockframework:spock-core:1.3-groovy-2.5'
testImplementation 'junit:junit:4.12'
}
}
When I compile the project using ./gradlew compileJava all works out fine and I get no compilation errors.
But when I run Rebuild Project withing IntelliJ I get a compilation error in module1 since IntelliJ does not have an annotation processor registered for module1.
Error:(6, 35) java: cannot find symbol
symbol: class PersonMapperImpl
location: class io.wangler.mapstruct.ApplicationModule1
Am I doing something wrong here or is this a known IntelliJ issue? The source code for this example can be found at https://github.com/saw303/idea-annotation-processors
I faced the same issue in IDEA 2019.3. Looks like a bug.
It occurs only if two modules has the same set of annotation processors.
To solve the problem you need to add any library using annotationProcessor directive to one of modules. It does not have to be a real annotation processor. This one is working for me:
annotationProcessor "commons-io:commons-io:${commonsIoVersion}"
I have created a defect in JerBrains bugtracker: IDEA-230337

How can I generate Mapstruct mapper implementations for test scope mapper interface in Gradle build?

I'm having a simple Java single module Gradle project in which I use Mapstruct for the Java mapping. My build.gradle looks like this:
plugins {
id 'java-library'
id 'groovy'
id 'net.ltgt.apt' version '0.20'
}
repositories {
jcenter()
}
dependencies {
implementation 'org.mapstruct:mapstruct-jdk8:1.2.0.Final'
annotationProcessor 'org.mapstruct:mapstruct-processor:1.2.0.Final'
testImplementation 'org.codehaus.groovy:groovy-all:2.5.5'
// Use the awesome Spock testing and specification framework even with Java
testImplementation 'org.spockframework:spock-core:1.2-groovy-2.5'
testImplementation 'junit:junit:4.12'
}
sourceSets {
main {
java {
srcDirs "${project.buildDir}/generated/sources/annotationProcessor/java/main"
}
}
test {
java {
srcDirs "${project.buildDir}/generated/sources/annotationProcessor/java/test"
}
}
}
My source folder contains the following Java source code:
src
├── main
│   ├── java
│   │   └── ch
│   │   └── silviowangler
│   │   ├── Person.java
│   │   ├── SomeMapper.java
│   │   └── User.java
│   └── resources
└── test
├── groovy
│   └── ch
│   └── silviowangler
├── java
│   └── ch
│   └── silviowangler
│   └── YoloMapper.java
└── resources
SomeMapper is a simple mapper interface that looks like this
#Mapper
public interface SomeMapper {
#Mappings({
#Mapping(target = "firstName", source = "nickname"),
#Mapping(target = "surname", ignore = true),
#Mapping(target = "dateOfBirth", ignore = true)
})
Person fromString(User user);
}
And the YoloMapper that resides in the test scope looks like that
#Mapper
public interface YoloMapper {
String fromLocalDate(LocalDate localDate);
}
When I run ./gradlew clean cTJ the build completes successfully and the annotation processor generates a mapper implementation for SimpleMapper but it does not generate anything for the YoloMapper. The build folder after the build looks like
build
├── classes
│   └── java
│   ├── main
│   │   └── ch
│   │   └── silviowangler
│   │   ├── Person.class
│   │   ├── SomeMapper.class
│   │   ├── SomeMapperImpl.class
│   │   └── User.class
│   └── test
│   └── ch
│   └── silviowangler
│   └── YoloMapper.class
├── generated
│   └── sources
│   └── annotationProcessor
│   └── java
│   ├── main
│   │   └── ch
│   │   └── silviowangler
│   │   └── SomeMapperImpl.java
│   └── test
└── tmp
├── compileJava
└── compileTestJava
How can I make Gradle to tell the annotation processor to generate Mapstruct mapper implementation in the test scope?
You need to configure the testAnnocationProcess configuration, as follows:
dependencies{
// for Main sources set
implementation 'org.mapstruct:mapstruct-jdk8:1.2.0.Final'
annotationProcessor 'org.mapstruct:mapstruct-processor:1.2.0.Final'
// for Test sources set
testAnnotationProcessor "org.mapstruct:mapstruct-processor:1.2.0.Final"
}

SPI + JDK 9 + module-info.java

I am experimenting with SPI on JDK 9. Entire example works on JDK 9 without "module-info.java". After adding "module-info.java" ServiceLocator is not finding implementing class. I am confused and I cannot find working SPI example in modulerized JDK 9 project.
So my example project looks like this:
/spidemo
├── apiModule
│   ├── pom.xml
│   └── src
│   └── main
│   └── java
│   ├── eu
│   │   └── com
│   │   └── example
│   │   └── text
│   │   └── spi
│   │   └── TextAPI.java
│   └── module-info.java
├── applicationB
│   ├── pom.xml
│   └── src
│   └── main
│   ├── java
│   │   └── eu
│   │   └── com
│   │   └── example
│   │   └── spi
│   │   └── b
│   │   └── application
│   │   └── DemoB.java
│   └── module-info.java
├── applicationCommon
│   ├── pom.xml
│   └── src
│   └── main
│   └── java
│   ├── eu
│   │   └── com
│   │   └── example
│   │   └── spi
│   │   └── application
│   │   └── TextAPIProvider.java
│   └── module-info.java
├── implementationB
│   ├── pom.xml
│   └── src
│   └── main
│   ├── java
│   │   └── eu
│   │   └── com
│   │   └── example
│   │   └── implb
│   │   └── text
│   │   └── TextB.java
│   ├── module-info.java
│   └── resources
│   └── META-INF
│   └── services
│   └── eu.com.example.text.spi.TextAPI
I have introduced interface:
package eu.com.example.text.spi;
public interface TextAPI {
String getHelloWorldText();
}
This interface is implemented by:
package eu.com.example.implb.text;
import eu.com.example.text.spi.TextAPI;
public class TextB implements TextAPI {
public String getHelloWorldText() {
return "Text from B implementation";
}
}
The implementation is searched by code simmiliar to:
package eu.com.example.spi.application;
import eu.com.example.text.spi.DefaultTextAPI;
import eu.com.example.text.spi.TextAPI;
import java.util.ServiceLoader;
public class TextAPIProvider {
public static TextAPI getProvider(String providerName) {
ServiceLoader<TextAPI> serviceLoader = ServiceLoader.load(TextAPI.class);
for (TextAPI provider : serviceLoader) {
String className = provider.getClass().getName();
if (providerName.equals(className)) {
return provider;
}
}
throw new RuntimeException(providerName + " provider is not found!");
}
}
And now is the fun part. When I am executing class below without:
/implementationB/src/main/java/module-info.java
/applicationB/src/main/java/module-info.java
then implementation class is found and text is printed out.
package eu.com.example.spi.b.application;
import eu.com.example.spi.application.TextAPIProvider;
public class DemoB {
public static void main(String[] args) {
System.out.println("---> " + TextAPIProvider.getProvider("eu.com.example.implb.text.TextB").getHelloWorldText());
}
}
After introducing this two "module-info.java" files implementation class is not found by ServiceLocator.
Content of /applicationB/src/main/java/module-info.java:
module eu.com.example.applicationB {
requires eu.com.example.apiModule;
requires transitive eu.com.example.applicationCommon;
uses eu.com.example.text.spi.TextAPI;
}
Content of /implementationB/src/main/java/module-info.java:
module eu.com.example.implb.text {
requires eu.com.example.apiModule;
exports eu.com.example.implb.text;
// provides eu.com.example.implb.text.TextB with eu.com.example.text.spi.TextAPI;
}
When I uncomment:
provides eu.com.example.implb.text.TextB with eu.com.example.text.spi.TextAPI;
line then compilation error occurs:
.../implementationB/src/main/java/module-info.java:[7,74] the service implementation type must be a subtype of the service interface type, or have a public static no-args method named "provider" returning the service implementation
.../implementationB/src/main/java/module-info.java:[7,5] service implementation must be defined in the same module as the provides directive
I have tried to change package names as compilation error sugests, but then I have introduced "split package" issues.
What I should do to use ServiceLocator in fully modularized JDK 9? Is it possible? Have anyone seen working example?
Code can be also seen here: https://github.com/RadoslawOsinski/spidemo
You can change to using:-
provides eu.com.example.text.spi.TextAPI with eu.com.example.implb.text.TextB;
// you provide a service through its implementation
instead of
provides eu.com.example.implb.text.TextB with eu.com.example.text.spi.TextAPI;
Services in the document provides a sample around the implementation.
A module can specify that it provides a service with a specific type of service providers. It is declared using provides and with keyword.
syntax : provides serviceType with implementationTypes;
( Can specify multiple implementations types as a comma-separated list )
Therefore in your module eu.com.example.implb.text should add following statement.
provides eu.com.example.implb.text.TextB with eu.com.example.text.spi.TextAPI;
NOTE : provides does not equal exports. So any other modules that requires eu.com.example.implb.text will not access eu.com.example.implb.text.TextB if it doesn't exports.

How should my MANIFEST.MF look?

I have the following directly structure:
mp1
├── lib
│   └── kryonet-2.21-all.jar
├── mp1.iml
├── out
│   ├── artifacts
│   │   └── UX
│   │   ├── META-INF
│   │   │   └── MANIFEST.MF
│   │   └── UX.jar
├── src
│   ├── [.class files]
│   └── cs425
│   └── mp1
│   ├── agent
│   │   ├── [handlers].java
│   ├── common
│   │   ├── [commons].java
│   ├── main
│   │   └── UX.java
│   └── network
│   ├── [networks].java
I'm completely new to mainfest files, and am just trying to get a .jar to run on a remote box. My manifest looks like this right now:
Manifest-Version: 1.0
Main-Class: cs425.mp1.main.UX
But I just keep getting,
~/mp1$ java -jar UX.jar
Error: Invalid or corrupt jarfile UX.jar
Any help? I'm not sure what options to add for my external library and how to define my classpath.
It appears as though the only thing I was missing was the classpath to my external .jar file. My manifest now looks like:
Manifest-Version: 1.0
Main-Class: cs425.mp1.main.UX
Class-Path: kryonet-2.21-all.jar
After making sure all of my required files are part of the artifact package (my manifest file, external jar, etc), the issue seems to have gone away.

Categories